架构总览
deepseek-harness(简称 dsh)是 DeepSeek 开源的 AI agent harness,仓库 README 第一句就给出了它的设计主张:
DeepSeek Harness (
dsh)… It uses an architecture where everything is a plugin, and is powered by Cordis…
这句"一切皆插件"不是宣传话术,而是仓库结构层面的工程约束。本页先给一张全景,再逐层下沉到后续章节。
分层全景
dsh 是一个 pnpm monorepo,自上而下分五层:
- CLI(
apps/cli):解析dsh命令行参数,按模式(profile/plugin/dump-config)动态启动。入口在apps/cli/src/bin.ts:27-52。 - Web UI(
apps/web):浏览器的 React 半,通过 RPC 与 host 半通信,展示会话、工具调用、Cordis 插件面板。 - Cordis 框架(
vendor/cordis):运行时核心,七个模块构成全部公共面vendor/cordis/src/index.ts:1-14。 - 能力插件(
packages/*):每个能力域(fs/shell/llm/mcp/session/… )都是独立 pnpm package + Cordis 插件,共 360+ 个包。 - 模式补丁层(
packages/bundle/*):用 YAML patch 把插件组合成"开箱即用的 bundle"——base是地基,headless/web-app是变体。
"一切皆插件"在仓库结构上如何体现
关键证据在 dsh-base bundle 的 patch 文件里。以下能力看似"核心",实则都是 patch 行:
packages/bundle/base/cordis.patch.yml:15-45 是 dsh-base bundle 的 insert 列表开头——timer/hmr/llm/session/typert/agent-default-model/jobs/settings 全部以 - id: <stable> 形式挂载,没有任何"特权模块"。更直白的是"每个模式都挂载的五行"packages/bundle/base/cordis.patch.yml:420-451:tools/system-prompt/agent-loop/fs-sandbox/llm-deepseek 是所有模式必挂的基础能力,其余能力在此之上 overlay。这意味着你可以 fork 任何一个 dsh-* 包替换它,而无需动其他包——没有"核心服务"硬编码在二进制里。
profile:用户私有的插件组合
dsh 不把插件列表写死在代码里,而是落在用户私有的 profile 目录:
initProfile在用户目录下建一个 pnpm workspace(pnpm-workspace.yaml)。dsh plugin add <pkg>实际执行pnpm add,把包写入依赖apps/cli/src/plugin.ts:120-158。- pnpm 跑完后
reconcilePlugins对照 before/after,新依赖若声明了dsh.bundle.patch就 push 进dsh.profile.bundles层栈;依赖移除或新版不再声明 bundle 则 splice 出apps/cli/src/plugin.ts:59-91。 - 如果新包带
dsh.bundle.patch,会被当成一个 bundle layer 加入层栈apps/cli/src/plugin.ts:36-45。
所以"装一个插件"=装一个 npm 包 + 对账 bundle 层栈,完全复用 pnpm 的依赖管理。
patch 的层叠顺序
cordis.patch.yml 不是普通配置,而是按层叠合并的 patch:
每条 patch 行有 id/name/config/disabled 四个字段。其中 disabled: !!js <expr> 是唯一被插值的元数据字段,每次挂载决策时对 loader context 求值——平台/环境差异(如 process.platform === 'win32')在此分流。!!js 表达式由 @deepseek-ai/cordis-plugin-include 在挂载时插值,允许 process.env/dshHomePath(...) 注入。
Cordis 框架的来源
Cordis 不是 DeepSeek 自己重写的,而是从 cordiverse/cordis vendor 进来的——即 Koishi 作者 Shigma 的 Cordis 框架,版本 4.0.1(上游 4.0.0-rc.7)。DeepSeek 把它 rescope 到 @deepseek-ai/cordis,并做了 18 处本地修改,文档化在 vendor/README.md 里,主要包含:
cordis/src/fiber.ts的生命周期硬化(修补了三个 reentrant disposal 漏洞)- 所有 package.json / tsconfig 重新生成
include/src/index.ts的applyEntryPatches抽出 + durable debounced writeshmr/src/index.ts移除 i18n YAML 依赖loader/src/config/entry.ts的disabled: !!js插值
同时 vendor 了 cosmokit/schemastery/loader/include/group/timer/hmr/logger-console 等上游 Cordis 生态包。这意味着理解 dsh 的运行时,本质是理解 Cordis 的 context/registry/service/fiber 模型——这正是后续 Cordis 框架 三章要讲的。
接下来读什么
- Cordis 上下文 — Context 这个被 Proxy 代理的根容器是什么
- 插件注册机制 — 静态注册与动态注册两套系统
- 插件加载与发现 — Loader 与 pnpm 如何协作