启航:环境、构建
与三种用法。
学习任何框架的第一课都不是读代码,而是把它跑起来。
这一课带你在自己机器上构建 DeepSeek Harness,用三种方式各跑一次,
并掌握全课程最重要的观察工具 --dump-config。
- 说清从源码跑起 dsh 的三个前置条件和验证方法
- 用 Web UI、headless、ACP 三种方式各执行一次任务
- 正确放置
DEEPSEEK_API_KEY,并诊断最常见的启动失败 - 用
--dump-config打印实际启动的插件树,为 L2 的组合配置打底
前置条件:三件套加一把钥匙
dsh 是 pnpm workspace 单仓,对工具链版本有明确要求。先把三件套备齐, 再决定要不要配置 API key——没有 key 也能构建和跑测试,只是用不了真实模型。
- Node.js
^22.19或>=24:package.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 成功退出。这也是之后每次改动前最基础的自检,记住它。
三分钟跑起来
$ 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),改源码立即生效——这是学习期最舒服的姿势。
完成构建后启动 Web UI,像普通用户一样完成一次对话(问它「这个仓库是做什么的」)。
pnpm install && pnpm run build && pnpm dsh web三种用法:同一颗内核,三张脸
dsh 的所有形态共享同一套插件化内核,区别只在最外层的「壳」。 理解这一点,你就理解了为什么这套 harness 能同时服务人类和程序。
- Web UI —
pnpm dsh web,浏览器里完整的对话界面,适合日常使用与观察 UI 保真度。本地启动会自动打开浏览器(--no-open可关闭)。 - Headless —
pnpm dsh --profile headless "帮我总结这个仓库",无头一次性运行,输出纯净日志,脚本友好,也最适合观察事件流。 - ACP / SDK — 自动化与编程接入同样走命名 profile:
pnpm dsh --profile acp起 ACP 自动化服务器;TypeScript 与 Python 两个 SDK 默认经sdkprofile(最小化场景用sdk-minimal)把同一条事件流投影给程序消费。
- 用 headless profile 跑一次无头任务,观察输出里的事件序列:
pnpm dsh --profile headless "用一句话介绍你自己"2. 对比 Web UI 里同一句话的交互——内核行为一致,只是外壳不同。
--dump-config:本课程最重要的观察工具
「一切皆插件」在文档里只是口号,--dump-config 让它变成你眼前一棵真实的树:
它打印当前 profile 实际组合出的完整插件配置——模型适配器、工具、会话、审批、loop 本身,全部在列。
dsh --profile web --dump-config读这份输出时记住一个事实:其中任何一行都能被你自己写的 patch 替换。 这不仅是观察工具,更是 L2 组合配置的预习——你看到的每一行,都是一个可以下手的扩展点。
把 dump 输出存成文件,每学完一课回去翻一次:L2 看结构,L5 找事件声明,L8 找工具注册。同一棵树,每课都有新发现。
常见坑:第一次启动失败怎么办
几乎所有第一次启动失败都指向同一件事——模型请求没配好。最典型的报错长这样:
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 时,真实 API 的 e2e 套件会自动跳过(CI 也一样,不会变红)——这是设计如此,不是测试坏了。 但 Web / headless / ACP 演示没有 key 就是跑不起来,二者不要混淆。
课堂练习
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 并重启进程即可;其余三项会在更早的阶段以别的错误形式暴露。
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 把这套框架调成自己想要的样子。