跳转至

01 · 项目全景与分层架构

全仓库面貌与五层架构:既看清整个 monorepo 的构成,也看清系统运行时每一层承担什么。

1. 项目全景

DeepSeek Harness(dsh) 是 DeepSeek AI 开源的一款 Agent 运行时(agent harness):它把"大模型对话 + 工具调用 + 会话管理 + 权限策略 + 沙箱执行"组装成一个可配置、可替换、可组合的运行时产品。通常的 agent 框架把主循环、工具注册、会话存储写死在框架里,只留少量扩展点;dsh 的定位反过来——它介于"框架"与"应用"之间:既提供完整可运行的 CLI / Web 产品,又提供可编程的插件生态。

三个标志性设计决策

  1. 无特权内核(no privileged core)。常规框架里总有几个"核心模块"是不可替换的;dsh 连模型适配器、工具注册表、会话日志、甚至 Agent 主循环本身都做成插件。扩展方式 = 在旁边再挂一个插件,而非修改内核。
  2. 事件溯源会话(event-sourced session)。会话是追加式事件日志,记录的是"发生了什么";模型可见的历史由日志 deriveMessages() 投影得出,绝不另存一份副本。"模型可见 ⟺ 已记录"是始终成立的性质。
  3. 框架层完全自持(vendored Cordis)。底层插件框架 Cordis 的源码直接 vendored 进仓库并改名 @deepseek-ai/*,附 18 项本地加固,因此整个框架层可审计、可补丁、可发布。

版本与格式策略

基线为上游 dsh-v0.2.2-alpha.2(developer preview,MIT 协议)。演进策略是"地基优先":会话格式版本保持 SESSION_FORMAT_VERSION,released 旧版本经相邻迁移链读入(session-format-v0-to-v1 / -v1-to-v2 / -v2-to-v3 / -v3-to-v4 + session-format-catalog:读路径 decode→migrate→encodeCurrent,写后继 generation、不动旧代),仅未发布/未知版本双向 fail loud;session-query 检索域 SQLite 使用单调 SCHEMA_VERSION。

2. 分层架构

下列表格描述上游 monorepo 的五层(mini 仓库的 core / web / webui 三层边界见根目录 README 与 architecture.md §3)。上游仓库是 pnpm monorepo(Node ^22.19 || >=24,全 ESM),各层之间只通过接口约定连接:

层 位置 职责 关键事实
应用层 apps/cli、apps/web CLI bin(dsh)与 Web GUI CLI 源码经 node --import tsx/esm 启动;bin 是"瘦自执行组合"
组合层 packages/bundle、preset、examples profile / bundle / preset 三种组合原语 bundle = 可分发补丁层;preset = 会话级 agent 组合;覆盖所有运行形态
能力层 packages/<group>/<pkg> 52 个包组、369 个子包(pnpm workspace packages/*/* 下含 package.json 的目录;基线 tag dsh-v0.2.2-alpha.2 / commit f3803c96974 树内计数),全部为能力扩展口 每包遵循 Service Definition / Provider / Consumer 三段式
框架层 vendor/ vendored Cordis + 生态(cosmokit、schemastery、loader、include、hmr 等) 全部改名 @deepseek-ai/*(含 @deepseek-ai/cordis);18 项本地修改有详单与测试
外部 SDK python/、packages/sdk Python SDK 与 TypeScript JSON-RPC SDK,跨进程驱动运行时 协议:stdio 换行分隔 JSON-RPC;Python 侧有官方 deepseek_harness 包

图 1:五层架构总览(应用 / 组合 / 能力 / 框架 / 外部 SDK)

flowchart TD
  subgraph L1["应用层 · apps"]
    A1["dsh CLI bin&lt;br/&gt;瘦自执行组合"]
    A2["Web GUI 宿主"]
  end
  subgraph L2["组合层 · bundle / preset / examples"]
    B1["profile 运行形态"]
    B2["bundle 可分发补丁层"]
    B3["preset 会话级 agent 组合"]
  end
  subgraph L3["能力层 · 52 包组 / 369 包 · 全部为能力扩展口"]
    C1["core:session / tools / agent / agent-loop"]
    C2["llm 适配 · shell · fs · sandbox"]
    C3["subagents · web · skills · persistence"]
  end
  subgraph L4["框架层 · vendor/(vendored Cordis + 生态)"]
    D1["@deepseek-ai/cordis 插件框架(18 项本地加固)"]
    D2["cosmokit · schemastery · loader · include · hmr"]
  end
  subgraph L5["外部 SDK 层"]
    E1["python/ deepseek_harness"]
    E2["packages/sdk TS JSON-RPC"]
  end
  A1 --> L2
  A2 --> L2
  L2 --> L3
  L3 --> L4
  E1 -.stdio JSON-RPC 子进程.-> A1
  E2 -.stdio JSON-RPC 子进程.-> A1

注:分层为本报告的学习归纳视角;上游架构文档(docs/architecture.md)以"核心包表 + 事件 + 能力扩展口 + 扩展点"组织,并无五层说法。图 1~15 均为此归纳视角下的示意。能力层向上提供"扩展口",组合层用 profile / bundle / patch 从中挑选具体 Provider,因此换一个 Provider 就换掉整个产品。所有图表需联网加载 Mermaid 渲染。

核心分层约束(最重要的一条架构纪律)

扩展插件只依赖 Service Definition,绝不依赖具体 Provider。 例如 UI、hook、工具插件只依赖 dsh-agent(接口),从不依赖 dsh-agent-loop(实现),所以主循环可整体替换。这是"换一个 Provider 就把整个产品换掉"的根本原因——文件系统/子进程/终端/LSP 共享一个执行世界,把 FS 与子进程 Provider 指向远程沙箱,Bash、PTY、LSP 全部随之迁移。