article: formalize DeepSeek Harness structure
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
{
|
||||
"title": "DeepSeek Harness 用插件构建 Agent",
|
||||
"title": "DeepSeek Harness 插件化架构与工程评估",
|
||||
"summary": "说明 Cordis 如何装配插件,插件如何通信,服务提供方如何选择,以及插件开发、测试和发布如何进行。",
|
||||
"date": "2026-08-14",
|
||||
"updated": "2026-08-14",
|
||||
@@ -18,7 +18,9 @@
|
||||
|
||||
调研冻结在 2026 年 8 月 14 日。目标代码为提交 [`47f943859bef60e4160492346772ded9b24f765a`](https://github.com/deepseek-ai/deepseek-harness/tree/47f943859bef60e4160492346772ded9b24f765a),该提交与调研日的远端 `HEAD` 一致。本文只评价 Harness 架构、工程流程和公开评测,不评价 DeepSeek 模型能力。
|
||||
|
||||
## Cordis 管理插件运行时
|
||||
## 一、DeepSeek Harness 的插件化架构
|
||||
|
||||
### 1.1 Cordis 插件运行时
|
||||
|
||||
DeepSeek Harness 的命令名是 `dsh`。它是一套 Agent 运行外壳:接收请求,调用模型,执行工具,保存会话,并向 Web、ACP 和 SDK 暴露入口。
|
||||
|
||||
@@ -39,7 +41,7 @@ dsh 主要使用 TypeScript 编写,运行在 Node.js ESM 环境。TypeScript
|
||||
|
||||
Cordis 负责前八项。它把配置变成一组可管理的插件实例,检查服务依赖,并在配置或依赖变化时卸载、重建相关实例。Agent loop 负责每次请求的执行。两者不在同一层。
|
||||
|
||||
## 启动和请求彼此分开
|
||||
### 1.2 插件运行时的启动流程
|
||||
|
||||

|
||||
|
||||
@@ -53,6 +55,8 @@ Fiber 常见状态为 `PENDING → LOADING → ACTIVE → UNLOADING`。插件声
|
||||
|
||||
插件通过 `ctx.on()` 注册监听器、通过 `ctx.tools.register()` 注册工具,或通过 `ctx.effect()` 管理连接和定时器。这些操作都会返回或绑定清理逻辑。Fiber 卸载时,Cordis 自动撤销它们。插件树表达的正是这种所有权和生命周期关系。
|
||||
|
||||
### 1.3 Agent 请求的执行流程
|
||||
|
||||

|
||||
|
||||
一次请求发生在插件全部就绪之后:
|
||||
@@ -66,7 +70,9 @@ Fiber 常见状态为 `PENDING → LOADING → ACTIVE → UNLOADING`。插件声
|
||||
|
||||
`SessionEvent` 在这条链路旁边记录事实。它保存用户消息、step、模型消息、工具调用、工具结果和最终回答,用于历史、恢复、fork 和 UI 投影;工具结果仍由 Agent loop 送回模型。[会话持久化](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/packages/session/session-persistence/README.md)
|
||||
|
||||
因此,插件树、依赖图和调用链不能混为一谈:
|
||||
### 1.4 插件树、依赖图与调用链
|
||||
|
||||
插件树、依赖图和调用链分别描述不同关系:
|
||||
|
||||
| 关系 | 回答的问题 | 示例 |
|
||||
|---|---|---|
|
||||
@@ -74,7 +80,7 @@ Fiber 常见状态为 `PENDING → LOADING → ACTIVE → UNLOADING`。插件声
|
||||
| 依赖图 | 谁必须等待哪项能力 | `tool-bash` 等待 `tools` 和 `shell` |
|
||||
| 调用链 | 一次请求经过哪些活跃组件 | Agent loop → LLM → Tools Runtime → shell → LLM |
|
||||
|
||||
## 插件通过三类接口协作
|
||||
## 二、插件协作的三类接口
|
||||
|
||||

|
||||
|
||||
@@ -86,9 +92,13 @@ Cordis 提供 Service 和 Event。dsh 在此基础上增加 Tool。三类接口
|
||||
| Event | 发布事件的插件 | 零到多个监听器 | 通知、策略和中间件 |
|
||||
| Tool | 模型 | Tools Runtime 和工具插件 | 模型发起的结构化动作 |
|
||||
|
||||
**Service 连接直接调用。** 定义包声明服务名和方法,provider 实现它,consumer 通过 `ctx.<name>` 调用。consumer 依赖服务名,不依赖具体 provider 包。一个 Context 内重复注册同名 Service 会直接报错,避免两个实现静默争用。
|
||||
### 2.1 Service 接口
|
||||
|
||||
**Event 连接松耦合协作。** 发布者只知道事件名、参数和分发语义,不知道谁在监听。监听器通过 `ctx.on()` 注册;它属于 effect,插件卸载时自动注销。
|
||||
定义包声明服务名和方法,provider 实现它,consumer 通过 `ctx.<name>` 调用。consumer 依赖服务名,不依赖具体 provider 包。一个 Context 内重复注册同名 Service 会直接报错,避免两个实现静默争用。
|
||||
|
||||
### 2.2 Event 接口
|
||||
|
||||
发布者只知道事件名、参数和分发语义,不知道谁在监听。监听器通过 `ctx.on()` 注册;它属于 effect,插件卸载时自动注销。
|
||||
|
||||
| 模式 | 执行方式 | 适用场景 |
|
||||
|---|---|---|
|
||||
@@ -100,7 +110,11 @@ Cordis 提供 Service 和 Event。dsh 在此基础上增加 Tool。三类接口
|
||||
|
||||
`waterfall` 的关键是 `next()`。监听器调用 `next()` 才会继续后续链路;不调用就会短路。选择错误的模式会改变执行顺序和失败语义,所以 Event 契约不只有参数类型,还必须说明分发模式。
|
||||
|
||||
**Tool 连接模型调用。** 插件用 `defineTool` 注册名称、描述、输入 Schema、输出 Schema 和 handler。模型只看到公开 Schema。调用进入 Tools Runtime 后,依次经过 `tools/pre-execute`、审批与 guard、`tools/execute`、handler、`tools/post-execute` 和结果固化。[Tools Runtime](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/packages/core/tools/README.md)
|
||||
### 2.3 Tool 接口
|
||||
|
||||
插件用 `defineTool` 注册名称、描述、输入 Schema、输出 Schema 和 handler。模型只看到公开 Schema。调用进入 Tools Runtime 后,依次经过 `tools/pre-execute`、审批与 guard、`tools/execute`、handler、`tools/post-execute` 和结果固化。[Tools Runtime](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/packages/core/tools/README.md)
|
||||
|
||||
### 2.4 接口契约的保障机制
|
||||
|
||||
TypeScript 接口只提供编译期检查,运行时会被擦除。交互由四层共同保障:
|
||||
|
||||
@@ -121,7 +135,9 @@ TypeScript 接口只提供编译期检查,运行时会被擦除。交互由四
|
||||
|
||||
只有前四类可能构成跨插件或外部契约。是否公开还要看它是否从 Definition package 导出,并在 subsystem 文档中出现。
|
||||
|
||||
## 配置决定服务提供方
|
||||
## 三、服务提供方的配置机制
|
||||
|
||||
### 3.1 shell 服务的分层结构
|
||||
|
||||
官方 shell 链路可以完整说明插件之间怎样协作。它分为 Definition(契约)、Provider(提供方)和 Consumer(使用方)三层。
|
||||
|
||||
@@ -171,6 +187,8 @@ ctx.tools.register(defineTool({
|
||||
|
||||
这条链路可以读成一句话:Profile 选择 provider,provider 注册 `shell`,Cordis 让 consumer 等待 `shell`,consumer 只调用 `ctx.shell`。因此它没有硬编码 `dsh-bash-local` 或 `dsh-bash-sandbox`。
|
||||
|
||||
### 3.2 服务提供方的追查方法
|
||||
|
||||
用户可以查看实际挂载结果,但目前没有一条命令直接输出完整的 `Service → Provider → 配置来源` 映射:
|
||||
|
||||
1. `dsh --profile web --dump-default-config` 查看 Profile 默认配置。
|
||||
@@ -180,7 +198,9 @@ ctx.tools.register(defineTool({
|
||||
|
||||
`dump-config` 解决“配置选择了什么”,inventory 解决“当前启动了什么”。inventory 不保留完整配置来源,也不直接反推 Service provider。这是当前排障能力的明确缺口。[Plugin inventory](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/packages/host/plugin-inventory/README.md)
|
||||
|
||||
## 插件接入遵循公开契约
|
||||
## 四、自定义插件的接入流程
|
||||
|
||||
### 4.1 扩展类型与接入点
|
||||
|
||||
开发新插件应先确定自己使用哪类扩展接口,再查对应的 Definition 和生成文档,无需遍历所有实现包。
|
||||
|
||||
@@ -195,48 +215,74 @@ ctx.tools.register(defineTool({
|
||||
|
||||
仓库提供三类索引:`cordis-surface` 文档列出 Service;`event-producer-consumer` 列出事件、分发模式、发布者和监听器;`tool-catalog` 列出模型可见 Tool Schema。高级 Cordis 组合还提供 `cordis_inspect_list/query`,可从当前仓库和运行时服务存储中查询 Service、Event、Tool 和 Slot。它们比遍历每个插件 README 更适合作为入口,但仍需要阅读目标 Definition 的语义和测试。
|
||||
|
||||
### 4.2 自定义插件开发流程
|
||||
|
||||
一个正常的自定义插件流程是:
|
||||
|
||||
1. 选择 Service、Event 或 Tool,不另造重复接口。
|
||||
1. 选择扩展接口。
|
||||
- 直接调用使用 Service。
|
||||
- 广播或中间件使用 Event。
|
||||
- 模型动作使用 Tool。
|
||||
2. 导入 Definition 包,只依赖公开类型和服务名。
|
||||
3. 声明 `inject`,并为配置定义运行时 Schema。
|
||||
4. 把监听器、工具和资源注册为 effect。
|
||||
5. 用 patch 挂载插件,先检查 `--dump-config`。
|
||||
6. 通过 inventory 确认 Fiber 已进入 `ACTIVE`。
|
||||
7. 增加单元测试和一次真实组合测试。
|
||||
8. 为会影响模型或用户的行为增加 keyless snapshot。
|
||||
3. 声明运行约束。
|
||||
- 硬依赖写入 `inject`。
|
||||
- 插件配置定义运行时 Schema。
|
||||
- 监听器、工具和资源注册为 effect。
|
||||
4. 用 patch 挂载插件。
|
||||
- 用 `--dump-config` 检查有效配置。
|
||||
- 用 inventory 确认 Fiber 已进入 `ACTIVE`。
|
||||
5. 补齐工程测试。
|
||||
- 增加单元测试和一次真实组合测试。
|
||||
- 影响模型或用户的行为增加 keyless snapshot。
|
||||
6. 固定兼容提交,再发布插件包。
|
||||
|
||||
动态 `cordis_define/run` 适合在当前进程里试验,但定义只存在于内存。进程重启后会消失,也不会生成插件包、安装依赖或写入 Profile。正式接入仍要落到插件包、配置和测试。
|
||||
|
||||
### 4.3 外部协议与进程边界
|
||||
|
||||
外部边界与进程内插件也应分开理解:Cordis 是进程内组合机制;Web 使用 HTTP 与 WebSocket;ACP 使用基于 stdio 的 newline-delimited JSON-RPC;SDK 使用项目自己的 line JSON-RPC 2.0;MCP 把外部工具注册进 Tools Runtime。MCP 当前主要桥接 Tool,Cordis 插件仍由进程内模块接口管理。[ACP](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/packages/acp/acp/README.md) [SDK 协议](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/packages/sdk/protocol/README.md) [MCP client](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/packages/mcp/mcp-client/README.md)
|
||||
|
||||
## 重启取决于变更类型
|
||||
## 五、插件变更与重启机制
|
||||
|
||||
### 5.1 配置变更
|
||||
|
||||
Profile 和 Harness home 的 `cordis.patch.yml` 会被监听。有效配置变化会事务式重算,相关 Fiber 和 effect 随之卸载或重建,通常不需要重启整个 dsh 进程。
|
||||
|
||||
### 5.2 代码变更
|
||||
|
||||
代码变更只有在挂载 `@deepseek-ai/cordis-plugin-hmr` 并覆盖目标路径时才会热替换。Web 客户端插件还需要 `pnpm run dev:web` 重建前端 bundle。生产环境升级 npm 包时,不能假设 HMR 一定覆盖新文件;除非部署明确启用了完整 watcher 链,否则应重启进程。
|
||||
|
||||
HMR 的行为是卸载旧 Fiber、加载新模块,再重建依赖方。前端新模块加载失败时,Fiber 会进入 `FAILED`,不会自动回滚到旧代码。因此关键插件更新仍需保留固定版本、健康检查和回退方案。[组合与 HMR](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/docs/cordis-tutorial/06-composition-and-hmr.zh.md)
|
||||
|
||||
## 改动经过仓库质量链
|
||||
## 六、仓库质量保障流程
|
||||
|
||||

|
||||
|
||||
仓库同时约束单包行为、真实组合、跨平台兼容和发布产物。
|
||||
|
||||
### 6.1 代码与文档的同步要求
|
||||
|
||||
代码按责任分区:`packages/*/*` 保存官方 Service、provider 和 consumer;`apps/*` 保存 CLI 与 Web 产品入口;`docs/` 和 `.agents/notes/` 保存公开契约与设计记录;`scripts/` 和 `.github/workflows/` 保存生成器、门禁和 CI。修改一项能力时,应从所属 package 开始,再同步它的 README、JSDoc、测试和必要的 Agent Note。[仓库布局](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/AGENTS.md)
|
||||
|
||||
| 阶段 | 主要要求 |
|
||||
|---|---|
|
||||
| 本地改动 | 同步代码、README、JSDoc、测试和 Agent Note |
|
||||
| 定向验证 | `pnpm run test` 跑单元测试;模型、协议或用户行为增加 `test:snapshot` |
|
||||
| 组合验证 | 产品可见插件要经 Loader、应用或进程入口验证,不能只手工构造 `ctx.plugin` |
|
||||
| 其他检查 | 按改动运行 `typecheck`、`lint`、`doc-sync`、`build`;真实 provider 才选 `test:e2e` |
|
||||
| Git hooks | pre-commit 检查翻译、lint、空白和生成文件;pre-push 执行 typecheck |
|
||||
| 内部 PR | 拆分独立改动;非 Draft PR 关联同仓 Issue,填写变更、验证和标签 |
|
||||
| CI | static、逐文件 100% coverage、snapshot、Node 兼容、Python、Wine 和 Windows |
|
||||
| 合并 | 聚合 `all checks passed`,进入 master 工作流 |
|
||||
| 发布 | 先构建和打包全部 DSH 成员,再验证安装产物;发布由 tag 和 environment 人工触发 |
|
||||
### 6.2 本地验证的三个层级
|
||||
|
||||
1. 验证单包行为。
|
||||
- 运行 `pnpm run test`。
|
||||
- 按改动运行 `typecheck`、`lint`、`doc-sync` 和 `build`。
|
||||
2. 验证真实组合。
|
||||
- 产品可见插件必须经过 Loader、应用或进程入口。
|
||||
- 只手工构造 `ctx.plugin` 不能替代组合测试。
|
||||
3. 验证模型和真实服务边界。
|
||||
- 模型、协议或用户行为增加 `test:snapshot`。
|
||||
- 真实 provider 才选择带密钥的 `test:e2e`。
|
||||
|
||||
### 6.3 提交、合并与发布流程
|
||||
|
||||
1. Git hooks 先检查翻译、lint、空白、生成文件和 typecheck。
|
||||
2. 内部 PR 拆分独立改动;非 Draft PR 关联同仓 Issue,并填写变更、验证和标签。
|
||||
3. CI 覆盖 static、逐文件 100% coverage、snapshot、Node 兼容、Python、Wine 和 Windows。
|
||||
4. `all checks passed` 聚合通过后,改动才能进入 master 工作流。
|
||||
5. 发布先构建和打包全部 DSH 成员,再验证安装产物;tag 和 environment 由人工触发。
|
||||
|
||||
逐文件 100% coverage 只是一项仓库门槛。行为质量还依赖真实组合测试和 keyless snapshot。真实 API e2e 使用密钥,只在可信事件运行;fork 和 Dependabot 会跳过,避免泄露 secret。[开发指南](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/docs/development.md)
|
||||
|
||||
@@ -244,7 +290,7 @@ HMR 的行为是卸载旧 Fiber、加载新模块,再重建依赖方。前端
|
||||
|
||||
本轮按要求没有重新运行 Harness 本地测试。上表描述冻结仓库定义的开发流程,不代表本轮测试已经通过。
|
||||
|
||||
## 外部贡献只能独立发布
|
||||
## 七、外部插件的发布方式
|
||||
|
||||
当前 [`CONTRIBUTING.md`](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/CONTRIBUTING.md) 明确说明项目仍处早期,暂不接受外部 Pull Request。官方建议外部开发者创建独立插件仓库,并使用 GitHub topic `dsh-plugin` 供用户发现。
|
||||
|
||||
@@ -252,12 +298,16 @@ HMR 的行为是卸载旧 Fiber、加载新模块,再重建依赖方。前端
|
||||
|
||||
如果目标是扩展 dsh,当前可执行路径是:基于公开 Definition 开发独立插件,锁定兼容提交,完成组合测试,发布自己的包和 `dsh-plugin` 仓库。只有官方重新开放外部 PR 后,主仓贡献链才成立。
|
||||
|
||||
## 公开评测仍然不足
|
||||
## 八、公开评测与证据边界
|
||||
|
||||
### 8.1 公开 Agent 任务评测
|
||||
|
||||
本文把“公开 Agent 评测”限定为同时给出任务或数据集、指标与分母、已测量结果。在冻结范围内,没有发现 SWE-bench、Terminal-Bench、AgentBench 或 GAIA 等 Agent 任务的公开成绩。
|
||||
|
||||
[`BENCHMARK.md`](https://github.com/deepseek-ai/deepseek-harness/blob/47f943859bef60e4160492346772ded9b24f765a/BENCHMARK.md) 只说明怎样用 Python SDK 启动 minimal agent,并为独立任务设置 workspace 和 session ID。它提供评测接入口,没有给出评测结果。
|
||||
|
||||
### 8.2 工程评测资产
|
||||
|
||||
仓库包含工程评测资产:
|
||||
|
||||
| 资产 | 指标 | 当前证据 |
|
||||
@@ -267,9 +317,23 @@ HMR 的行为是卸载旧 Fiber、加载新模块,再重建依赖方。前端
|
||||
| CI runner benchmark | 不同平台和 core 数下的检查耗时 | 用于 CI 容量,与 Agent 能力评测无关 |
|
||||
| 单元、snapshot、e2e | 类型、行为、组合和真实 API 链路 | 证明工程链路,不证明任务成功率 |
|
||||
|
||||
缺失的评测至少包括:固定模型和预算下的任务成功率、工具调用正确率、权限拒绝与恢复率、断点恢复正确率、长会话质量、插件组合兼容性,以及相同任务上的对照 Harness。没有这些结果,就不能从高覆盖率推导出 Agent 效果。
|
||||
### 8.3 评测缺口
|
||||
|
||||
## 当前只适合受限试点
|
||||
缺失的评测至少包括:
|
||||
|
||||
- 固定模型和预算下的任务成功率。
|
||||
- 工具调用正确率。
|
||||
- 权限拒绝与恢复率。
|
||||
- 断点恢复正确率。
|
||||
- 长会话质量。
|
||||
- 插件组合兼容性。
|
||||
- 相同任务上的对照 Harness。
|
||||
|
||||
没有这些结果,就不能从高覆盖率推导出 Agent 效果。
|
||||
|
||||
## 九、采用建议
|
||||
|
||||
### 9.1 当前采用判断
|
||||
|
||||
| 阶段 | 当前判断 | 条件 |
|
||||
|---|---|---|
|
||||
@@ -279,11 +343,19 @@ HMR 的行为是卸载旧 Fiber、加载新模块,再重建依赖方。前端
|
||||
|
||||
DeepSeek Harness 当前标注 Developer Preview,会主动发生兼容性变化;会话格式仍为 v0;调研日未见正式 GitHub Release。这些事实不否定架构价值,但会放大插件兼容、会话迁移和运维成本。
|
||||
|
||||
合理的下一步是选择一个低风险任务做隔离试点:固定版本;保留 `workspace-write + ask`;逐项确认 shell、文件、Web 和外部服务是否真的进入审批策略;保存有效配置和 plugin inventory;把升级、会话导出和插件回退都当作可能失败的步骤。
|
||||
### 9.2 受限试点要求
|
||||
|
||||
合理的下一步是选择一个低风险任务做隔离试点:
|
||||
|
||||
1. 固定版本。
|
||||
2. 保留 `workspace-write + ask`。
|
||||
3. 逐项确认 shell、文件、Web 和外部服务是否进入审批策略。
|
||||
4. 保存有效配置和 plugin inventory。
|
||||
5. 把升级、会话导出和插件回退都当作可能失败的步骤。
|
||||
|
||||
只有在固定任务集上取得可复现结果,并补齐安全、发布和迁移责任后,才应重新讨论默认采用。
|
||||
|
||||
## 结论基于冻结源码
|
||||
## 十、调研范围与证据
|
||||
|
||||
- 目标仓库:[deepseek-ai/deepseek-harness](https://github.com/deepseek-ai/deepseek-harness)
|
||||
- 冻结提交:[`47f943859bef60e4160492346772ded9b24f765a`](https://github.com/deepseek-ai/deepseek-harness/tree/47f943859bef60e4160492346772ded9b24f765a)
|
||||
|
||||
Reference in New Issue
Block a user