CHAPTER 01 · STAGE 01 · 建立项目地图

如何使用这套教材

学习 DeepSeek Harness 的目标不是把两百多个 workspace 包背下来。真正有用的能力只有四项:看到一个包时能判断它负责什么;看到一个事件时知道它属于持久日志还是运行时控制;看到一个功能需求时知道应该挂在哪个扩展点;修改后知道需要哪一层测试证明它真的工作。

你最终要获得什么能力

学习 DeepSeek Harness 的目标不是把两百多个 workspace 包背下来。真正有用的能力只有四项:看到一个包时能判断它负责什么;看到一个事件时知道它属于持久日志还是运行时控制;看到一个功能需求时知道应该挂在哪个扩展点;修改后知道需要哪一层测试证明它真的工作。

学完后,你应该能完成下面的任务:

  1. 从用户输入追踪到模型请求、工具调用和最终回复。
  2. 解释 ctx.tools、ctx.llm、ctx.sessions 和 ctx.agents 分别由谁提供、由谁消费。
  3. 在不修改 agent-loop 的前提下添加一个工具、策略或上下文插件。
  4. 为改动选择单元测试、真实组合测试或快照测试。

不要采用“从第一个目录读到最后一个目录”的方法

大型仓库的目录结构表达所有权,不表达教学顺序。packages/core/session 可能依赖 packages/llm/llm 的消息类型,packages/core/agent-loop 又同时使用 Session、LLM、Tools、System Prompt 和 Agent。按照字母顺序或目录顺序阅读,会不断遇到还没有建立的概念。

更好的方法是围绕一个真实动作建立纵向切片。例如研究 Bash 时,只追踪三层:shell 定义能力、bash-local 实现能力、tool-bash 把能力交给模型。其他包先不展开。

每次学习只做四件事

1. 看一个场景

先问“用户做了什么”。例如:用户说“列出当前目录”,模型决定调用 Bash,系统执行命令,再把结果发回模型。

2. 画一条数据流

不要一开始画完整架构图。只画本次场景经过的对象:

UserMessage → Agent → LLM → ToolCall → Shell → ToolResult → LLM

3. 打开不超过三个源码文件

第一次追踪只看入口类型、主要实现和一个测试。测试经常比实现更容易说明“这个包承诺什么行为”。

4. 用自己的例子复述

把 bash 换成“天气查询”或“读取文件”。如果替换例子后仍能解释 Definition、Provider、Consumer 的关系,才说明概念已经掌握。

阅读源码时固定问六个问题

遇到任何插件,先回答:

  1. 它在 ctx 上提供哪个 Service?
  2. 它通过 inject 依赖哪些 Service?
  3. 它注册哪些事件监听器、工具或提示词片段?
  4. 注册是否有 disposer,插件卸载后会清理什么?
  5. 它产生的内容是否会被模型看到?如果会,内容如何进入 Session 日志?
  6. 它的失败应该在哪一层被观察或恢复?

这六个问题比“每一行代码是什么意思”更重要。前者帮你找到结构,后者只会让你陷入局部细节。

学习节奏

建议每篇分两次完成。第一次用 30 到 45 分钟阅读并画图;第二次用 30 到 60 分钟打开源码、运行测试并完成练习。

如果某篇出现三个以上陌生术语,先去常用概念词典查词,再回到原文。不要为了一个术语跳进十层源码。

打卡格式

每次学习后用下面四项汇报:

完成内容:读了哪一篇,打开了哪些源码
运行结果:运行了什么命令,成功或失败
我的解释:用自己的话讲清一个概念
仍不明白:只写一个最阻碍继续学习的问题

这种格式能区分“已经看过”和“已经理解”。运行成功不等于理解,解释正确也不等于能操作;两者都需要。

第一阶段的合格标准

在进入 AgentLoop 之前,你至少要能解释:

  • 插件为什么通过 ctx 获取服务,而不是直接导入具体实现。
  • inject 为什么不是普通的导入语句。
  • ctx.effect() 为什么与热重载和资源释放有关。
  • cordis.yml 为什么描述的是插件树,而不只是配置值。

如果这些问题答不出来,继续读 AgentLoop 只会看到大量陌生方法调用,却无法理解它们为什么这样组织。