L1 · 启航
Lesson 01 · 模块 A · 会用

启航:环境、构建
与三种用法。

学习任何框架的第一课都不是读代码,而是把它跑起来。 这一课带你在自己机器上构建 DeepSeek Harness,用三种方式各跑一次, 并掌握全课程最重要的观察工具 --dump-config

精读 20 分钟 练习 10 分钟 · 6 题 前置
学完你将能够
  • 说清从源码跑起 dsh 的三个前置条件和验证方法
  • 用 Web UI、headless、ACP 三种方式各执行一次任务
  • 正确放置 DEEPSEEK_API_KEY,并诊断最常见的启动失败
  • --dump-config 打印实际启动的插件树,为 L2 的组合配置打底
01 · Prerequisites

前置条件:三件套加一把钥匙

dsh 是 pnpm workspace 单仓,对工具链版本有明确要求。先把三件套备齐, 再决定要不要配置 API key——没有 key 也能构建和跑测试,只是用不了真实模型。

  • Node.js ^22.19>=24package.json 的 engines 字段写死了这个范围(CI 覆盖 22.19、24、26)。版本不对,后面全是玄学问题。
  • Corepack 启用的 pnpm:仓库锁定 pnpm@11.7.0。不要全局另装 pnpm,跑 corepack enable 让 Node 自带的分发器接管,版本自动对齐。
  • Git 2.26+:克隆与 worktree hooks 需要。
  • (可选)DEEPSEEK_API_KEY:写在仓库根目录的 .env 文件里(已被 gitignore)。可选 DEEPSEEK_BASE_URL 指向兼容端点。永不提交凭据。
# .env(仓库根目录,gitignored) DEEPSEEK_API_KEY=sk-... # DEEPSEEK_BASE_URL=https://api.deepseek.com # 可选,默认公共 API
验证方法

环境就绪的自检只有一条:pnpm run typecheck 成功退出。这也是之后每次改动前最基础的自检,记住它。

02 · First Run

三分钟跑起来

$ git clone https://github.com/deepseek-ai/deepseek-harness.git $ cd deepseek-harness $ pnpm install $ pnpm run build $ pnpm dsh web # → http://127.0.0.1:3080

pnpm install 除了装依赖,还会做两件容易忽略的事:通过 scripts/install-lefthook.mjs 配置 worktree 本地的 Lefthook git hooks, 以及注册双语档合并用的 git merge driver。如果依赖是从缓存恢复、postinstall 被跳过, 手动执行 node scripts/install-lefthook.mjs 补齐。

pnpm run build 产出两层产物:tsc 编译出的 lib/types,以及 tsdown 打包的运行时。 之后的 pnpm dsh从源码启动 CLI(经 tsx 的 ESM hook),改源码立即生效——这是学习期最舒服的姿势。

动手试 · 2 分钟

完成构建后启动 Web UI,像普通用户一样完成一次对话(问它「这个仓库是做什么的」)。

pnpm install && pnpm run build && pnpm dsh web
03 · Three Faces

三种用法:同一颗内核,三张脸

dsh 的所有形态共享同一套插件化内核,区别只在最外层的「壳」。 理解这一点,你就理解了为什么这套 harness 能同时服务人类和程序。

Web UI pnpm dsh web · 浏览器对话 Headless CLI --profile headless "任务" ACP / SDK 自动化协议 · 双语言 SDK 同一颗插件化内核(Cordis + agent loop + 工具 + 会话日志) cordis.yml 组合 · 所有部件可替换 外壳只负责输入输出:浏览器界面、一次性命令、编辑器协议。内核行为完全一致。
图 1-1 · 三种形态共享同一内核。学会一种,其余两种只是换壳。
  • Web UIpnpm dsh web,浏览器里完整的对话界面,适合日常使用与观察 UI 保真度。本地启动会自动打开浏览器(--no-open 可关闭)。
  • Headlesspnpm dsh --profile headless "帮我总结这个仓库",无头一次性运行,输出纯净日志,脚本友好,也最适合观察事件流。
  • ACP / SDK — 自动化与编程接入同样走命名 profile:pnpm dsh --profile acp 起 ACP 自动化服务器;TypeScript 与 Python 两个 SDK 默认经 sdk profile(最小化场景用 sdk-minimal)把同一条事件流投影给程序消费。
动手试 · 3 分钟
  1. 用 headless profile 跑一次无头任务,观察输出里的事件序列:
pnpm dsh --profile headless "用一句话介绍你自己"

2. 对比 Web UI 里同一句话的交互——内核行为一致,只是外壳不同。

04 · X-Ray

--dump-config:本课程最重要的观察工具

「一切皆插件」在文档里只是口号,--dump-config 让它变成你眼前一棵真实的树: 它打印当前 profile 实际组合出的完整插件配置——模型适配器、工具、会话、审批、loop 本身,全部在列。

dsh --profile web --dump-config

读这份输出时记住一个事实:其中任何一行都能被你自己写的 patch 替换。 这不仅是观察工具,更是 L2 组合配置的预习——你看到的每一行,都是一个可以下手的扩展点。

学习建议

把 dump 输出存成文件,每学完一课回去翻一次:L2 看结构,L5 找事件声明,L8 找工具注册。同一棵树,每课都有新发现。

05 · Pitfalls

常见坑:第一次启动失败怎么办

几乎所有第一次启动失败都指向同一件事——模型请求没配好。最典型的报错长这样:

dsh: TRANSPORT: DeepSeek API request to https://api.deepseek.com failed [ELIFECYCLE] Command failed with exit code 1.
  • 没配 key:在仓库根目录建 .env,写入 DEEPSEEK_API_KEY=sk-...,重启进程(环境变量是启动时读取的)。
  • key 无效或额度耗尽:先确认 key 本身可用,再怀疑网络。
  • 走代理/私有端点:用 DEEPSEEK_BASE_URL 指向你的兼容端点。
陷阱 · 测试与 key 的关系

没有 key 时,真实 API 的 e2e 套件会自动跳过(CI 也一样,不会变红)——这是设计如此,不是测试坏了。 但 Web / headless / ACP 演示没有 key 就是跑不起来,二者不要混淆。

06 · Quiz · 10 分钟

课堂练习

2 单选 + 2 多选 + 2 问答。选择即时批改,问答先写下你的答案再对照。成绩保存在本地浏览器。
单选
验证 dsh 开发环境已经就绪,官方推荐的自检命令是哪一条?

pnpm run typecheck 成功退出即 setup 完成——它同时验证了依赖安装、workspace 链接和 TS 工程引用。测试可以没有 key 而跳过,Web 需要 key,只有 typecheck 是无条件的全量自检。

单选
运行 pnpm dsh --profile headless "任务"TRANSPORT: DeepSeek API request ... failed,最可能的原因是?

TRANSPORT 层失败发生在请求 DeepSeek API 的途中,头号嫌疑就是 key:没配、失效或额度耗尽。在仓库根目录 .env 写入 DEEPSEEK_API_KEY 并重启进程即可;其余三项会在更早的阶段以别的错误形式暴露。

多选
从源码跑起 dsh 的前置条件包括哪些?(选出所有正确项)

C 是陷阱:没有 key 也能 clone、install、build、跑单元测试——key 只影响真实模型调用(Web / headless / ACP 演示和 e2e 测试,后者会自动跳过)。A、B、D 是文档写明的前置条件。

多选
关于 pnpm install--dump-config,哪些说法正确?

B 错:dump 的是实际组合出的运行配置,不是源码索引。D 错:没有 key 时真实 API e2e 套件自动跳过,CI 不会因此变红。A、C 都是本课正文的原话。

问答为什么说「先当用户,再当读者」是学习这套框架的第 0 步,而不是可选项?写下答案后点击对照

参考要点:① 没有上下文的通读效率最低——先亲手触发一次核心流程,之后读代码时每个概念都有亲身体验可以挂靠;② --dump-config 让「一切皆插件」从口号变成眼前真实的插件树,是后续所有理解的支点;③ 三种外壳共享同一内核的体感,只有亲手跑过才能建立。

问答Web UI、headless、ACP 三种用法的关系是什么?这个设计对你使用框架有什么实际好处?写下答案后点击对照

参考要点:三者共享同一颗插件化内核(同一 cordis.yml 组合、同一 agent loop、同一事件流),区别只在最外层负责输入输出的壳。实际好处:学会一种形态就等于学会全部;调试时用 headless 观察纯净事件流,演示用 Web UI,自动化集成用 ACP/SDK——按场景选壳,不用重新学习内核行为。

本课小结

你已经把框架跑起来了:三件套环境、typecheck 自检、三种用法各跑一次、 用 --dump-config 看到了插件树的全貌,还知道了第一坑(TRANSPORT 失败 = 先查 key)。 下一课我们放大这棵树:读懂 cordis.yml,学会用 profile 和 patch 把这套框架调成自己想要的样子。