返回知识库
0

第一章:总体架构

本章目标:帮助你建立对 DeepSeek Harness 的全局认知——它是什么、为什么存在、技术栈如何选型、核心抽象有哪些、包布局如何组织、运行时启动链如何工作。阅读本章后,你应该能回答"如果我要修改某个功能,应该去哪个目录找代码"。


1.1 什么是 DeepSeek Harness

DeepSeek Harness(以下简称 dsh)是一个全插件化的 Agent 运行时框架。它的设计目标是:

  1. 所有能力都是插件:模型适配器、工具注册、会话日志、Agent 循环本身——每一个都是可替换的 Cordis 插件。

  2. 没有特权核心:你通过在配置中挂载一个插件来扩展 dsh,而不是通过修改核心代码。

  3. 配置驱动组合:一个运行中的 dsh 实例是从有序的配置层(称为 Profile 和 Bundle)组合而成的插件树。

简单来说:dsh 是一个 Agent 运行时基础设施,让开发者能通过配置文件而不是写代码来组装一个完整的 AI Agent。

预览
源码

dsh 运行时

Cordis 插件框架

Agent Loop

LLM 适配器

工具注册表

会话持久化

用户交互层

...其他插件

配置文件 cordis.yml

dsh CLI

graph TB
    subgraph "dsh 运行时"
        A[Cordis 插件框架] --> B[Agent Loop]
        A --> C[LLM 适配器]
        A --> D[工具注册表]
        A --> E[会话持久化]
        A --> F[用户交互层]
        A --> G[...其他插件]
    end
    H[配置文件 cordis.yml] --> A
    I[dsh CLI] --> H

1.2 技术栈

层次技术选择说明
语言TypeScript (ESM)所有包使用 "type": "module",纯 ESM
运行时Node.js ^22.19 或 >=24利用 Node 原生 TypeScript 支持和最新的模块 API
包管理pnpm WorkspacesMonorepo 管理,workspace 协议链接
插件框架Cordis (vendored)源码级内置于 vendor/,完整控制框架层
类型验证Schemastery + Zod配置 schema(Schemastery)和运行时数据 schema(Zod)
构建tsdown (bundling) + tsc (类型)tsdown 打包运行时,tsc 生成类型声明
测试Vitest单元测试、快照回放、端到端测试

为什么 Vendored Cordis

Cordis 是一个通用的插件框架(cordiverse/cordis),dsh 选择源码级内嵌而非 npm 依赖,原因:

  1. 完全审计:框架代码和产品代码在同一个 monorepo,可 diff、可审查

  2. 本地修补:当发现框架 bug 时,可以直接修复而无需等待上游发版

  3. Scope 重命名:所有 vendored 包从上游名字重命名为 @deepseek-ai/*,避免在 npm 上抢占上游包名

Vendored 包的完整清单(来自 vendor/README.md):

目录npm 名称上游版本
cosmokit/@deepseek-ai/cosmokit1.8.1
schemastery/@deepseek-ai/schemastery3.18.0
cordis/@deepseek-ai/cordis4.0.0-rc.7
loader/@deepseek-ai/cordis-plugin-loader1.0.0-rc.5
include/@deepseek-ai/cordis-plugin-include1.0.4
group/@deepseek-ai/cordis-plugin-group1.0.0
timer/@deepseek-ai/cordis-plugin-timer1.1.2
hmr/@deepseek-ai/cordis-plugin-hmr1.0.15
logger-console/@deepseek-ai/cordis-plugin-logger-console1.0.0

1.3 包布局总览

仓库根目录结构:

deepseek-harness/
├── apps/           ← 应用入口(CLI)
├── packages/       ← 所有 @deepseek-ai/dsh-* 工作区包
├── vendor/         ← Vendored Cordis 源码
├── docs/           ← 架构文档、生成的目录、手册
├── scripts/        ← 仓库门控脚本和生成器
├── python/         ← Python SDK 和运行时
├── native/         ← Node 原生 addon (Landlock)
├── .agents/        ← Agent 工作流和笔记
└── tutorial/       ← 本教程

核心包组

packages/ 下按能力族分组(完整的组映射见 packages/README.md):

预览
源码

编排

能力插件

core/ 核心

会话事件日志

Prompt 段落组装

工具注册表

Agent 接口

交互

interaction/

context/

guard/

数据平面

session/

compaction/

credentials/

llm/ LLM

服务定义

llm/llm

llm/llm-deepseek

core/session

core/agent-loop

core/system-prompt

core/tools

core/agent

shell/

fs/

lsp/

web/

skill/

subagent/

workflow/

preset/

graph LR
    subgraph "core/ 核心"
        A[core/session] -->|会话事件日志| B[core/agent-loop]
        C[core/system-prompt] -->|Prompt 段落组装| B
        D[core/tools] -->|工具注册表| B
        E[core/agent] -->|Agent 接口| B
    end

    subgraph "llm/ LLM"
        F[llm/llm] -->|服务定义| G[llm/llm-deepseek]
    end

    subgraph "能力插件"
        H[shell/] --> I[fs/]
        I --> J[lsp/]
        J --> K[web/]
        K --> L[skill/]
    end

    subgraph "编排"
        M[subagent/]
        N[workflow/]
        O[preset/]
    end

    subgraph "数据平面"
        P[session/]
        Q[compaction/]
        R[credentials/]
    end

    subgraph "交互"
        S[interaction/]
        T[context/]
        U[guard/]
    end

    B --> M
    B --> N
    D --> H

以下是各包组的职责概要:

包组职责代表包
core/产品 API 脊柱core/session, core/agent, core/agent-loop, core/tools, core/system-prompt
llm/LLM 能力llm/llm(抽象服务), llm/llm-deepseek(DeepSeek 实现)
session/持久化数据面session/session-persistence-jsonl(JSONL 后端), session/session-projection
tools/模型面向的工具每个能力插件注册一个或多个工具 schema
bundle/可安装的 Patch 层bundle/headless, bundle/web-app, bundle/sdk-app, bundle/acp-app
boot/启动胶水boot/app-boot(Profile 加载 + Cordis 初始化)
extensions/运行时扩展extensions/cordis-host-runner, extensions/cordis-client-runner
interaction/人类协作interaction/user-approval, interaction/user-questions
credentials/凭证与授权credentials/authorization
sdk/JSON-RPC SDKsdk/server, sdk/client

1.4 核心抽象

在深入各子系统之前,先理解 dsh 的几个核心抽象:

1.4.1 Session(会话)

一个 Session 是一次 Agent 与用户的完整交互。它包含:

  • SessionHeader:元数据(ID、创建时间、配置)

  • SessionEventLog:一个仅追加的事件流,记录所有用户消息、助手回复、工具调用等

  • 内存状态:运行时维护的投影(projection),从日志增量派生

// 来自 packages/core/session/src/types.ts
interface SessionHeader {
  // 会话标识、创建时间、配置等
}

核心设计原则Model-visible ⟺ logged——任何到达模型请求的内容都必须可从日志重建。

1.4.2 Agent(智能体)

Agent 是一个可取消的工作单元,拥有:

  • Inbox:接收用户消息和注入上下文

  • Step:一次模型请求 + 工具调用序列

  • Turn:零或多个 Step,从 claim input 到 close

// 来自 packages/core/agent/src/index.ts
interface AgentFactory {
  createAgent(options: CreateAgentOptions): AgentHandle
}

interface AgentHandle {
  // 句柄:取消、状态查询等
}

1.4.3 Capability Seam(能力接缝)

能力接缝是 dsh 中可替换能力的设计模式,由三个角色组成:

  1. Service Definition:声明接口

  2. Service Provider:实现接口

  3. Consumer:使用接口,通常是面向模型的工具

预览
源码

Service Definition
ctx.llm

Service Provider
DeepSeek Adapter

Consumer
agent-loop

graph LR
    SD[Service Definition<br/>ctx.llm] --> SP[Service Provider<br/>DeepSeek Adapter]
    SD --> C[Consumer<br/>agent-loop]
    SP --> C

关键洞察:一个 provider 的切换就能改变整个产品。文件系统和子进程 provider 共享同一个执行世界,所以把它们指向远程沙箱就能同时移动 Bash、PTY 和 LSP。

1.4.4 Profile(配置档)

Profile 是一个命名的插件组合,存储在 Harness home 中。它:

  • 列出它堆叠的 Bundle

  • 保存用户自己的 cordis.patch.yml

  • 保持 out-of-tree 插件的安装状态

1.4.5 Bundle(捆绑包)

Bundle 是 Cordis 配置行和它们挂载的代码的分发格式。一个 Bundle 声明自己在 package.jsondsh.bundle 字段中。

层次叠加顺序:

预览
源码

空 Entry 列表

dsh-base Bundle

Profile Bundle
如 headless/web/sdk

Profile 的 cordis.patch.yml

Home 级 cordis.patch.yml

--patch 覆盖层

graph TB
    A[空 Entry 列表] --> B[dsh-base Bundle]
    B --> C[Profile Bundle<br/>如 headless/web/sdk]
    C --> D[Profile 的 cordis.patch.yml]
    D --> E[Home 级 cordis.patch.yml]
    E --> F[--patch 覆盖层]

1.5 运行时启动链

当用户运行 dsh --profile headless "task" 时,以下是发生的完整链条:

预览
源码
Plugin TreeCordis Runtimeapp-bootprofile-boot.tsdsh CLI(apps/cli)UserPlugin TreeCordis Runtimeapp-bootprofile-boot.tsdsh CLI(apps/cli)Userdsh --profile headless "task"runProfile(profile, args)loadProfile(profileName)解析 bundle 列表加载各 bundle 的 patch 文件组合 cordis.patch.yml应用 --patch 覆盖配置好的 entry 列表boot(emptyRootConfig)按序应用各 patch 层每个 entry 作为 patch 应用插件挂载、服务注册Agent Loop 启动LLM 适配器就绪工具注册表就绪ready signalcommit()Agent 开始执行任务
sequenceDiagram
    participant User
    participant CLI as dsh CLI<br/>(apps/cli)
    participant PB as profile-boot.ts
    participant AB as app-boot
    participant Cordis as Cordis Runtime
    participant Tree as Plugin Tree

    User->>CLI: dsh --profile headless "task"
    CLI->>PB: runProfile(profile, args)
    PB->>AB: loadProfile(profileName)
    AB->>AB: 解析 bundle 列表
    AB->>AB: 加载各 bundle 的 patch 文件
    AB->>AB: 组合 cordis.patch.yml
    AB->>AB: 应用 --patch 覆盖
    AB-->>PB: 配置好的 entry 列表

    PB->>Cordis: boot(emptyRootConfig)
    Cordis->>Tree: 按序应用各 patch 层
    Tree->>Tree: 每个 entry 作为 patch 应用
    Tree->>Tree: 插件挂载、服务注册
    Tree->>Tree: Agent Loop 启动
    Tree->>Tree: LLM 适配器就绪
    Tree->>Tree: 工具注册表就绪
    Tree-->>PB: ready signal
    PB-->>CLI: commit()
    CLI->>User: Agent 开始执行任务

关键源码文件

文件职责
apps/cli/src/profile-boot.tsCLI 启动入口,解析 Profile、堆叠 Patch 层、挂载 Cordis 树
packages/boot/app-boot/src/profile.tsloadProfile() 实现,Bundle 加载、Patch 组合
vendor/cordis/src/context.tsCordis 上下文(Context 类),服务注册中心
vendor/loader/src/index.tsCordis Loader,解析 cordis.yml 配置
vendor/include/src/index.tsCordis Include,配置 Patch 层的应用逻辑

启动参数流

启动参数不是 launcher 的业务。profile-boot.ts 将参数通过 ctx.cmdlineArgs 提供给插件树,任何注入的 app 插件都可以读取这个不可变快照。


1.6 事件体系

dsh 使用三种事件域来解耦系统:

1.6.1 Session Events(会话事件)

持久化事实,追加到日志并通过 session/event 广播。用于需要存活过重载的事实。

// 来自 packages/interaction/user-approval/src/types.ts
interface SessionEventMap {
  // 所有会话事件类型在此声明
  // 每个事件都是仅追加的事实
}

1.6.2 Agent Events(Agent 事件)

agent/* 域,携带一个活的 Agent:inbox、step、status、request、validation、continuation。用于观察或拦截进行中的工作。

1.6.3 Capability Events(能力事件)

附加策略和适配器到接缝(fs/*tools/*telemetry/*),不导入循环本身。

事件派发模式

模式等待?派发顺序返回值?用途
emit注册顺序通知观察者
waterfall注册顺序中间件,next() 委托
parallel并行扇出
serial注册顺序有序执行
bail直到 bail短路

1.7 Turn 流程概览

一个 Turn 是一次完整的 Agent 交互:

turn/start
  claim next-step input + 排队消息
  组装 prompt sections + tool schemas
  -> agent/pre-step                    reject | enter(messages)
     reject 或空 enter → 关闭 turn(无 step)
     step/start
     追加消息为 user/message
     从日志派生模型历史
     agent/request -> llm/stream -> assistant/chunk* -> assistant/message
     tool/call* -> tools/pre-execute -> tools/execute -> tools/post-execute -> tool/result*
     step/end
     工具欠另一个请求,或下一个 input 到达 -> claim -> 下一步
  -> agent/turn-stopping
turn/end

关键事实

  • turn/*step/*user/messageassistant/*tool/*持久化会话事件

  • 其余(agent/pre-stepagent/requestllm/streamtools/*)是活的扩展点

  • Waterfall 事件(agent/pre-stepagent/requestllm/stream、三个 tools/*)的监听者必须调用 next() 来委托


1.8 小结

概念一句话解释
Cordis插件框架,所有功能通过它组装
Profile命名的插件组合配置
Bundle可分发的配置行 + 代码
Session一次交互的完整记录(仅追加日志)
Agent可取消的工作单元,拥有 Inbox
TurnAgent 一次完整交互(多个 Step)
Step一次模型请求 + 工具调用
Capability Seam可替换能力的三角色模式

下一步第二章:环境与运行——了解如何搭建开发环境、理解 CLI 启动过程和 Profile 机制的细节。

DeepSeek-Harness / 01-总体架构 0 0 LinDoo
2026-09-04T03:25:33.901508021Z 2026-09-04T07:52:40.387412647Z