摘要:DeepSeek Harness(dsh)是一个以"一切皆插件"为架构信条的 Agent 开发框架,其底层由仅约 2000 行 TypeScript 的元框架 Cordis 承担"微内核"角色。本文以完整源码索引为证据,逐一剖析 Cordis 的插件规范五要素——Plugin、Context、Service、Typed Events、Effects——在 Harness 中的真实落地形态,并提炼出六个关键架构实践:能力接缝三层模式、事件即系统契约、双端跨界复用、运行时自我修改、声明式组合语言、以及"插件结构即工程结构"。文章最终论证:Cordis 之于 dsh,不仅是"软件总线",更是让 Agent 系统获得可演化、可自举能力的"进化底座"。
一、一个 2000 行内核,如何撑起一个 Agent 操作系统?
It uses an architecture where everything is a plugin, powered by Cordis.
"一切皆插件"并不是一句口号,而是一组可以量化的工程事实:54个npm 包组、约219个模块,全部以@deepseek-ai/dsh-*的插件形态存在;而它们的共同宿主,是被vendor进仓库、重命名为@deepseek-ai/cordis的 Cordis 框架核心——一个核心代码仅约 2000行TypeScript、只专注于"插件的加载、卸载与依赖关系管理"的元框架。
这构成了一个耐人寻味的比例关系:一个 2000 行的内核,承载了 7404 个文件、2319 个 TypeScript 源文件的完整 Agent 产品。本文的核心问题因此而生:Cordis 究竟凭借什么机制,让如此庞大的功能体系能够以高度模块化、可热插拔、可扩展、甚至可自我修改的方式被构建出来?
二、微内核策略:为什么 DeepSeek 选择"vendor 而非依赖"
2.1 vendor 目录:九个包的"框架族"
在DeepSeeK harness源代码中可以看到完整的vendor布局:
|
|
|
|
cordis/ |
@deepseek-ai/cordis |
框架核心:Context、Service、Fiber、类型化事件
|
cosmokit/ |
@deepseek-ai/cosmokit |
共享工具(框架与 Schemastery 的基础)
|
schemastery/ |
@deepseek-ai/schemastery |
|
loader/ |
@deepseek-ai/cordis-plugin-loader |
cordis.yml
|
include/ |
@deepseek-ai/cordis-plugin-include |
|
group/ |
@deepseek-ai/cordis-plugin-group |
|
timer/ |
@deepseek-ai/cordis-plugin-timer |
|
hmr/ |
@deepseek-ai/cordis-plugin-hmr |
|
logger-console/ |
@deepseek-ai/cordis-plugin-logger-console |
|
值得注意的细节是:连"加载器、配置包含、插件组、HMR、日志"这些本该属于框架层的设施,在 Cordis的世界里本身也是插件。这恰恰印证了Cordis的元框架本性——内核只提供运行时原语,其余一切皆可插件化、可替换。
2.2 内嵌而非引用的深层原因
DeepSeek将Cordis源码内嵌(vendor)并重新划入自家scope,而非作为普通npm依赖引入,索引中记录了18处本地修改。这一决策至少包含三层逻辑:
-
深度定制:作为整个系统的微内核,任何语义调整(如作用域链、生命周期时序)都会波及全部 54 个包组。vendor使DeepSeek可以像维护自家代码一样修改内核,并通过rescope脚本与verify-runtime-closure等门禁保证一致性。
-
版本钉死与供应链控制:pinned source +pnpm-workspace.yaml的 overrides/patches,配合verify-cordis-config.ts等源码门禁,确保"内核不变式"在每次构建中都被校验。
-
生态基座:vendor的9个包构成了完整的"框架族"——schemastery为每个插件提供 Schema 校验,loader/include提供声明式组装,hmr提供热更新。DeepSeek 不是重新发明轮子,而是把轮子焊进自家底盘。
三、插件规范五要素:从概念到Harness的实证落地
Cordis的插件化构建围绕五个核心概念展开。源码索引为每一个概念都提供了大量实证。
3.1 Plugin 与 Plugin Registry:54 个包群的注册表
Cordis的Plugin Registry负责管理所有已安装插件的元数据与依赖关系。在dsh中,这一机制被放大为一种组织结构:packages/<group>/<pkg>/的目录即注册表分类,而docs/下的生成式目录(config-catalog.md、tool-catalog.md、module-graph.md)则是注册表的"可读投影"。每一个能力族——core、api、llm、sandbox、fs、shell、subagent、web、session……——都是一个插件群,由注册表统一编目。
3.2 Context:插件的"工作台",以及被 dsh 扩展出的"作用域链"
每个插件拥有独立的Context,通过ctx访问服务、注册资源。dsh 并未止步于此,而是在core/scope中实现了dsh-scope:带标签的 Cordis 上下文、父子作用域链。这一扩展的意义在于:Context 不再仅仅是插件隔离的边界,更成为 Agent 隔离的边界。
-
dsh-agent:提供 "process-local initiator scope"——每个Agent在其作用域内启动;
-
dsh-subagent-spawn-in-process/dsh-subagent-fork-in-process创建"全新的子作用域"或"继承父历史的作用域";
-
子代理、终端、持久化shell(ctx.terminals的 "exact-Agent ownership")都以作用域为单位声明归属。
可以说,dsh把Cordis的Context层级抽象,升级为Agent 级的多租户隔离模型——这是对元框架原语的一次重要上卷。
3.3 Service:能力接缝(Capability Seam)
dsh源代码最显著、最系统的模式,是几乎每个能力族都遵循的三层结构:
|
|
① Service Definition(接口契约)
|
|
③ Model-facing Tool(对模型暴露)
|
|
|
dsh-fs
|
dsh-fs-local
|
dsh-tool-fs
|
|
|
dsh-subprocess
|
dsh-subprocess-local |
|
|
|
dsh-shell
|
dsh-bash-local
/ dsh-bash-sandbox / dsh-pwsh-*
|
dsh-tool-bash
、dsh-tool-bash-persistent
|
|
|
dsh-sandbox
|
dsh-sandbox-local
(bwrap/Landlock/Seatbelt/Windows ACL)
|
|
|
|
dsh-code-runtime
|
dsh-code-runtime-worker-thread |
|
|
|
dsh-lsp
|
dsh-lsp-stdio |
dsh-tool-lsp |
|
|
dsh-terminal
|
dsh-terminal-bash |
dsh-tool-terminal
|
|
|
dsh-llm
|
dsh-llm-deepseek
|
|
|
|
dsh-session-persistence |
...-jsonl
|
|
|
|
dsh-web
|
Exa / Perplexity / DeepSeek / HTTP-fetch
|
dsh-tool-web |
|
|
dsh-subagent
|
in-process / ACP / Codex / Claude Code / dsh-sdk
|
dsh-tool-subagent
|
这一模式的本质,是 Cordis Service +inject机制的系统化应用:
-
第①层(Definition)声明"能力存在什么",通常作为一个注册表/契约插件存在;
-
第②层(Provider)通过ctx注册具体实现——一个能力可以有多个并存的实现(如 bash 有 local 与 sandbox 两种执行器);
-
第③层(Tool)则是"模型可见面",把内部服务调用翻译为模型可调用的工具 schema。
依赖关系完全由inject声明,Cordis 保证插件运行前其依赖服务已就绪。之前我做的源代码索引中有大量可互证的注入链,例如:
-
dsh-bash-sandbox "wraps argv through ctx.sandbox"——shell 执行器注入沙箱服务;
-
dsh-lsp-stdio" over ctx.fs + ctx.subprocess"——LSP 后端同时注入文件系统与子进程两个服务;
-
dsh-tool-bash-persistent "over one owner-scoped persistent ctx.terminals shell"。
这就是"可替换性"的结构性来源:切换 LLM 提供商、沙箱后端、持久化后端、搜索提供商,都只是配置层面的Provider更换,接口契约(Service Definition)纹丝不动。
3.4 Typed Events:事件的"系统词汇表"与横切关注点
Cordis 的类型化事件是插件间松耦合通信的通道。dsh将这一机制升华为系统级契约:每个核心插件不仅提供服务,还声明一套事件词汇表:
-
-
dsh-tools:工具执行的pre / execute / post-execute事件;
-
-
dsh-compaction:compaction/*事件词汇表;
-
dsh-command-feedback:feedback/record事件;
-
dsh-llm-retry:通过agent/request-error瀑布实现提供商级重试策略。
其中dsh-llm-retry是一个教科书级的事件驱动横切关注点案例:重试逻辑没有被打进任何LLM适配器,而是作为一个独立的插件监听agent/request-error事件链来实施策略。同理,策略门禁类插件(如dsh-fs-observation-policy、dsh-spill-policy、dsh-tool-call-timeout-policy)都以"事件钩子/包装器"的形式插入既有管线,而不是侵入被包装者。
更值得注意的是,dsh用工程手段把"事件词汇表"从隐式约定变成显式文档:scripts/gen-scoped-events.ts生成docs/event-producer-consumer.md(事件矩阵:声明者、分发者、监听者)。类型化事件由此获得了"编译期可查、文档化可审"的契约地位。
3.5 Effects 与 Fiber:生命周期状态机与"零垃圾"卸载
Cordis的Fiber是插件的运行时实例与生命周期状态机(PENDING → LOADING → ACTIVE → DISPOSED);Effect 则是插件注册的可撤销副作用,卸载时自动清理。这一机制在dsh中的痕迹遍布源码:
-
热更新:vendor 的cordis-plugin-hmr+dsh-client-hmr(浏览器端插件热重载)、dsh-app-boot的"config-only HMR"——只有副作用可逆,热重载才可能安全;
-
有序关停:apps/cli的process-shutdown.ts是"有界/升级式进程退出控制器"(SIGINT=130、SIGTERM=0);
-
确定性清理:dsh-terminal明确要求 "awaited cleanup"(等待式清理),dsh-session-persistence有 "write coordination"。
Fiber的生命周期管理,正是dsh能够支持"运行时挂载/卸载插件"(见 4.4)而不留下资源泄漏的根基。
四、Cordis机制在Harness中的具体工程形态
4.1 服务定义与提供者分离 → 可替换性
已在 3.3 详述。补充一个极端例子:沙箱能力族中,dsh-sandbox-local覆盖 Linux(bwrap/Landlock)、macOS(Seatbelt)、Windows(ACL restricted-token runner)四套后端,其中 Landlock 后端甚至下沉为 C11 原生插件(native/landlock-run,约300行、fail-closed exit)。原生代码也以插件身份进入系统——这是"一切皆插件"的最彻底注脚。
4.2 声明式组合语言:cordis.yml、Profile、Preset与Patch 层
dsh的"系统如何组装"本身是可编程、可分层、可快照的:
每个可运行叶子(examples/:acp-agent、headless-agent、jsonrpc-agent、mcp-memory、web-cordis、web-schedule)都持有自己的cordis.yml;
-
apps/cli 支持--profile、--patch、--dump-config,profile-boot.ts负责"解析 profile、叠加 patch 层、挂载插件树";
-
apps/cli/config/agent-presets/ 内置四个 Agent 预设(code/、cordis/、minimal/、standard/),每个预设 =agent.cordis.yml+preset.yml;
-
vendor 的cordis-plugin-include提供配置包含与补丁叠加(applyEntryPatches、!!js方言);
-
dsh-app-boot 实现"快照感知配置、settle-tree 启动",配置变更可通过 HMR 生效。
组合起来,dsh 的配置系统形成了一条完整的"组合语言"链路:cordis.yml(声明)→ Schemastery(Schema 校验)→ Loader(解析与缓存)→ Include(分层叠加)→ Profile/Preset(场景化组装)。--dump-config与config-catalog.md则让"系统最终长什么样"可预览、可审计。
4.3 双端插件化:同一个插件模型跨越进程边界
dsh的Web GUI是本文分析中最具说服力的跨界案例:插件模型同时运行在Node宿主进程与浏览器中。
-
宿主端(packages/host/):dsh-host-apiproxy(类型化 API 网关)、dsh-host-webserver、dsh-host-frontend-static、dsh-host-directory-picker(原生/浏览/自适应三种后端)——全是 Cordis 插件;
-
浏览器端(packages/client/,@deepseek-ai/dsh-client-*):dsh-client-web是"两阶段启动(模块面 + 插件面)"的浏览器内核;dsh-client-modules模拟 Node的ESM loader;dsh-client-hmr在浏览器里实现插件热重载;数十个dsh-client-ui-*组件本身就是浏览器端插件;
-
类型化RPC:typert/家族(generator/loader/registry/protocol)通过@Remote/@RemoteScope生成跨端服务描述,使宿主端ctx.typert Gateway与浏览器端ctx.remote的服务调用类型安全。
这意味着Cordis的"插件=作用域+服务+事件+生命周期"语义,被原样复刻到了浏览器——UI 开发与后端开发遵循同一套心智模型。dsh-client-ui-slots甚至刻意做成 "React-free、cordis-free" 的槽位注册表核心,为UI组合提供不依赖渲染框架的组合原语。
4.4 运行时自我修改:把"插件系统"交给 Agent 自己
这是Cordis微内核架构最惊人的回报。packages/extensions/实现了一条完整的运行时动态插件链:
-
dsh-cordis-host-runner:定义注册表 +node:vm沙箱 + "request-run 往返"(ctx.dynamicCordisRunner)——把 Agent 写出的插件定义在 VM 中求值并实时挂载;
-
dsh-cordis-client-runner:浏览器端对应物,把定义求值为真实浏览器插件;
-
dsh-tool-cordis:对模型暴露"运行时检查 + 动态包"工具;
-
dsh-client-ui-cordis:帧级面板与只读定义卡片。
对应示例examples/web-cordis/被描述为"自指演示:Agent检查并挂载自己的 Cordis插件"。这只有在"一切皆插件 + Fiber生命周期可逆 + Effects自动清理"的前提下才可能安全成立:Agent 挂载一个插件失败或卸载时,系统不会留下任何残骸。插件化在这里完成了从"工程手段"到"产品能力"的跃迁——Agent获得了自我扩展的能力。
4.5 可观测与不变式:插件结构即工程结构
dsh 把 Cordis 的插件结构本身用作工程质量基础设施:
-
dsh-invariants:(runtime-diagnostics/invariants)提供可配置不变式注册表(ctx.invariants),每个包都发布一个./invariant伴生模块——插件结构成了挂载运行时断言的统一位置;
-
scripts/ 中约 150 个门禁脚本,包括verify-package-invariants.ts、verify-runtime-closure.ts、verify-cordis-config.ts等,在CI层校验"插件世界"的完整性;
-
生成式文档(gen-cordis-catalog.ts、gen-cordis-api.ts、gen-module-graph.ts)直接从源码产出docs/cordis-api/、config-catalog.md、module-graph.md——文档结构由插件结构自动推导,杜绝文档漂移。
4.6 测试与演示即插件:test-support 与 examples
测试设施同样遵循插件范式:dsh-llm-replay(无密钥回放记录的模型响应)、dsh-llm-mock-server(确定性故障服务器)都是可以替换LLM Provider插件的测试插件;dsh-agent-loop-testkit、dsh-client-test-runtime(jsdom 槽位运行时)、dsh-loader-smoke各自针对不同层次。连Python SDK的捆绑运行时(deepseek-harness-runtime-bin)都内嵌一份cordis.yml(sdk-jsonrpc-server+ agent-spine-demo+ llm-deepseek+ JSONL持久化,约 110 个插件依赖)——跨语言、跨运行时,依然是同一套声明式组装。
五、收益分析:插件化构建兑现了哪些架构承诺
|
|
|
|
|
54 包组 / ~219 模块按能力族组织;module-graph.md 生成依赖图
|
|
|
每个能力族的 Definition/Provider 分离;LLM、沙箱、持久化、搜索、子代理均有多个可切换实现
|
|
|
HMR 插件、config-only HMR、客户端插件热重载;Fiber+Effects 保证卸载零残留
|
|
|
docs/cookbook/
提供"新增包/新增工具/新增 LLM 适配器"的标准化路径
|
|
|
replay/mock/snapshot/testkit 均为插件,可无侵入替换
|
|
|
dsh-tool-cordis
+ VM 运行器:Agent 可在运行期挂载自写插件
|
|
|
生成式目录、事件矩阵、不变式门禁、505 条已实现 Agent Notes(决策记录)
|
六、代价与挑战:硬币的另一面
-
vendor的维护成本:18 处本地修改 +rescope-vendor.ts+ 同步流程,意味着每次上游 Cordis 升级都是一次移植手术;索引明确标注 "Do not edit vendor/*/src/ casually"。
-
兼容性风险:0.1.0-rc.5 处于 developer preview,索引声明 "compatibility-breaking changes expected"——插件契约(Service 签名、事件词汇表)的任何变更都会波及 54 个包。
-
复杂性的上移:微内核把复杂性从内核转移到了组合层——composition.md(生成的 dsh-base 插件树 Mermaid 图)、verify-runtime-closure.ts、knip.json死代码分析等,都是为驾驭这种组合复杂性而生的"制动器"。
-
认知门槛:dsh 用docs/cordis-primer.md(Cordis教程)与 7 章cordis-tutorial(01-first-plugin → 07-into-the-harness)来降低插件作者的入门成本——这本身就说明"插件心智"是需要系统培养的。
七、结论:Cordis之于dsh,是"软件总线",更是"进化底座"
回到最初的比例问题——2000行内核如何撑起 54 个包组?答案在于Cordis提供的不是功能,而是关系的语法:
-
Context与Fiber:定义了组件的边界与生命周期;
-
Plugin Registry:是管理所有组件的目录;
-
Service与inject:定义了组件间"接口/实现/依赖"的语法;
-
Typed Events:定义了组件间"通知/响应"的语法;
-
Effects:定义了"可逆性"这一让热插拔与自修改成为可能的根本属性。
DeepSeek Harness 的真正创新,不在于发明了这些原语,而在于以惊人的纪律性把整个产品——从LLM适配到文件系统、从沙箱到浏览器UI、从测试设施到Agent自身——全部翻译成了这套语法。于是"一切皆插件"不再是修辞,而是一种可量化、可验证、可自动生成的工程状态。也正因如此,dsh才获得了其他Agent框架罕见的属性:系统可以在运行时检查自己、修改自己、并安全地卸载自己。
Cordis是dsh的软件总线;但更重要的是,它是dsh的进化底座——一个让Agent系统既能稳健地组合,又能开放地自举的微内核。这或许是"元框架 + 插件架构"这一组合在 Agent 领域最有说服力的一次工业级实践。