DeepSeek Harness 源码解读
0.1.0-rc.5、一个 Release 都没发、README 里有一句全大写的破坏性变更警告,
所以文中所有命令、配置与默认值都带时效,请以仓库最新内容为准。
第三,这个项目会在你本机执行工具、运行 shell 与子进程,仓库自己在三处明写隔离
不是安全边界,是否使用请结合自身环境评估。
本专题分两批写成,核对日分别是 2026-08-16 与 2026-08-17,
对应同一个仓库快照 47f9438。
末尾那一组横向对照另用了 Claude Code 官方文档、Codex 与 Pi 两个开源仓库作为对照方,
只对照各方公开写明的机制,不对三者做优劣排名。
本专题共 100 篇。内容依据
官方仓库
的 README、docs/ 下的架构与子系统文档、以及 packages/ 下的源码整理。
文中出现的阈值与默认值均为源码中的默认配置,
不构成对实际运行结果的保证;star 数与 issue 数带 2026-08-16 时间锚点,
且不能由它们推导质量结论。
DeepSeek Harness 是什么:建仓三天、13 万 star 的 Agent 框架
DeepSeek Harness 自称是「一切皆插件」的 agent harness,跑在内联进仓的 Cordis 上;但截至 2026-08-16 它建仓只有三天、版本停在 0.1.0-rc.5、一个 Release 都没发。本文只依据仓库快照能核对的文件与数字,讲清它自述是什么、49 个组目录与 219 个真实包怎么切、三条运行路径各带什么前置条件,以及几处文档与磁盘对不上的地方。
认识与工程门槛
README 只给了一句「Install Node.js」,而 Node 版本门槛其实只钉在那个 private 的根包上——我们扫过的 230 份 manifest 没有一份带 engines。这一组还包括两条运行路径各自的前置条件、一份笔记标着 implemented 而代码直接报错的 --host 0.0.0.0,以及一个仓库为什么要七份 vitest 配置。
npx @deepseek-ai/dsh web 是做什么的?默认端口 3080 与 Node 版本门槛
这条命令是 DeepSeek Harness 的 README 里唯一一条不用克隆仓库的路径,跑起来会启动 Web UI,默认服务在 127.0.0.1:3080。但 README 只说「装 Node.js」,根 package.json 声明的却是 ^22.19.0 || >=24.0.0,而这条门槛不会随发布出去的包被 npm 校验到。本文把这条路和从源码构建、Python SDK 两条路的前置条件、默认值出处与已写明的限制逐条对上。
DeepSeek Harness 的 Node 门槛:230 份 manifest 没一份写 engines
DeepSeek Harness 的 README 只说「装个 Node.js」,全仓写死版本范围的只有根 package.json,而根包标着 private。本文数清这 230 份 manifest,把这个门槛在 manifest、AGENTS、开发文档与 CI 矩阵四层的口径摆到一起,并给出起不来时的判定路径。
DeepSeek Harness 的 --host 0.0.0.0:笔记说已实现,代码直接报错
DeepSeek Harness 仓库里关于 dsh web 的绑定地址,Agent Note、CLI 参考与子系统文档给出了三种不同说法,其中一处标着 implemented 却与源码里的判断相反。本文逐条列出三处的文件路径与原文,说明该去哪一层找权威口径,并给出可自查的判定动作与排除条件。
DeepSeek Harness 中英文档怎么防漂:1078 组配对与 blob hash 校验
DeepSeek Harness 把中英双语文档的一致性做成了可机器校验的事:每对文档配一个 .i18n.yaml,记两侧的 git blob hash。本文沿仓库里的 i18n 契约文档与校验脚本走一遍:它记的是什么、为什么用 blob hash 而不用 commit hash、这个 gate 又承认管不到什么。
DeepSeek Harness 为什么要七份 vitest 配置:测试分层怎么切的
DeepSeek Harness 仓库根目录躺着七个 vitest 文件与五个 tsconfig 文件。本文按快照 47f9438 逐个读它们的文件头注释、行数与关键常量,讲清这套分层是按「每条 lane 花什么代价」切开的,以及 npm scripts、CI gate 与 Windows 侧各自能核到哪一步。
Cordis 内核与「一切皆插件」
这句宣传语的技术底座是被内联进仓的 Cordis。这一组从最小插件、服务注册、事件派发一路读到 scope 继承,中间会撞上几处口径差:入门文档列四种派发模式而源码是五种,术语表说 scope 扁平不继承而源码实现了带环检测的父子链,vendor/ 里九个包的版本号跟自家 manifest 表全对不上。
DeepSeek Harness 的「一切皆插件」:Cordis 到底承担了什么
「一切皆插件」是 DeepSeek Harness 的 GitHub 简介原文。本文回到 2026-08-16 的仓库快照,看这句话在 README、AGENTS.md 与架构文档里怎么写,vendored 进来的 Cordis 内核有多大,packages 下的包为什么全都依赖它,以及这套范式带来的三种静默失败。
DeepSeek Harness 最小插件怎么写:apply、ctx 与插件生命周期
顺着 deepseek-harness 仓库里 Cordis tutorial 第一章的三行代码往下读,把最小插件的入口函数 apply、被传进来的 ctx 到底是什么、以及一个插件从 PENDING 到 DISPOSED 的完整状态流转讲清楚,途中标出每一处的文件与行号,方便你自己回仓库核对。
DeepSeek Harness 的服务注册与取用:inject 声明与 ctx 服务约定
DeepSeek Harness 的插件不靠 import 找彼此,而是把能力挂到 context 上、用 inject 声明依赖。本文照着 vendored Cordis 的源码与仓库自带的教程,走一遍服务从注册到 ctx.tools 取用的路径,说清 PENDING 是什么、依赖缺失为何不报错、诊断该看哪几个字段。
DeepSeek Harness 的 Cordis 事件派发:文档四种、源码是五种
DeepSeek Harness 的 Cordis 入门文档说事件派发模式有四种,而 tutorial、生成的 API 文档与 vendor/cordis 源码里的 DispatchMode 类型都是五种,多出来的是 bail。本文标出这四处的行号,给出自己核对的动作,并说明生成的事件矩阵里为什么看不到 bail。
DeepSeek Harness 的 Cordis scope:术语表说扁平,源码是父子链
DeepSeek Harness 的术语表把 agent scope 写成「两层、扁平、不向下继承」,而 scope 包源码的 JSDoc 写的是一条同时向下继承注册视图、向上扩展事件准入的父子链,还带环检测。本文摆出这两处原文与确切行号,并给出你自己回仓库核对的四步动作。
DeepSeek Harness 的 vendor 九个包:版本号与实读全对不上
DeepSeek Harness 把 Cordis 全家桶源码放进 vendor/,并在 vendor/README.md 维护了一张九行 manifest 表。本文逐个打开这九个 package.json,记录表中版本号与实读 version 的九行差异、两处文档写到却缺席的 private 字段,并给出自查脚本。
架构与包体系:数字最容易在这里翻车
packages/ 下用 ls 数出 49 个目录,但工作区 glob 是两层,真实 npm 包有 219 个——写「49 个包」就错了。这一组还包括 219 个包统一的版本口径、AGENTS.md 里那两个不存在的目录、能力接缝图里四个找不到对应包的名字,以及同一个 core 被三份文档分别说成 6、7、8 个子包。
DeepSeek Harness 到底有多少个包:49 是数错了,真实是 219 个
在包目录下一眼数出 49 个文件夹,很多人据此写成「49 个包」。但工作区 glob 是两层的 packages/*/*,那 49 个只是组目录、自己没有 package.json,真正的 npm 包在第二层,截至 2026-08-16 共 219 个。本文给出复核脚本,以及几个容易搞混的数字。
DeepSeek Harness 的 219 个包版本全是 0.1.0-rc.5:发布口径怎么读
deepseek-harness 的 packages 下有 219 个真实 npm 包,截至 2026-08-16 它们的 version 全是 0.1.0-rc.5,而 GitHub 上一个 Release 都没有。本文拆开讲怎么数包、版本号统一到什么程度、哪些包不走这套口径,并给出可自行复核的统计脚本。
DeepSeek Harness 的 AGENTS.md 分组清单:两个目录不存在、漏 17 个
按 2026-08-16 快照,把 DeepSeek Harness 根 AGENTS.md 的 Repository layout 清单与 packages/ 真实目录逐行比对:两个组名没有对应目录,17 个真实组没列进去,它指向的 packages/README.md 分组表少两个组。本文标出每处差异位置与复核法。
DeepSeek Harness 能力接缝图:四个包名在 packages 下找不到
deepseek-harness 的 docs/capability-seams.md 里有四个包名在 packages/ 树下没有对应目录。这篇沿着这四个名字,走一遍从生成脚本到改名台账的定位路径,说清它们各自登记在哪一行、哪些名字只是组前缀差异不算失效,以及这条判定在什么情况下不成立。
DeepSeek Harness 的 core 有几个子包:三份文档分别说 6、7、8
DeepSeek Harness 的 packages/core 有几个子包?目录里是 8 个,组 README 的表列 7 行,docs/subsystems/core.md 首句写「六个包」,架构页那张 7 行表还混进了别组的包。本文给出这几处的确切位置与包名清单,说明组目录与真实子包为什么得分开数。
会话、上下文与压缩
一次会话从事件到投影再到落盘经过哪几层,上下文放不下时往哪溢出。这一组的四篇都落在可核对的常量上:文档写三种压缩事件而源码声明了四个,token 计量的第三种 baseline 文档没提,四个都叫 version 的数字分属四套 schema,还有一个已经从源码里消失、却还留在文档与生成脚本里的 TurnTrigger。
DeepSeek Harness 的会话生命周期:事件、投影与持久化三层
DeepSeek Harness 把一次会话拆成三层:只增不改的事件日志、从日志派生的模型可见消息、负责落盘的持久化 seam。本文沿 turn/step 时序走一遍这三层,标出 seq 契约、44 个已知事件类型、200 毫秒写批处理窗口与崩溃恢复补边界的位置,依据 2026-08-16 的仓库快照整理。
DeepSeek Harness 的压缩事件有几个:文档三种、源码四个
DeepSeek Harness 压缩子系统文档写着 three event types 且只列三行表格,源码 types.ts 的 declare module 块却声明了四个,多的是 compaction/prune。本文标出两处口径的文件与行号,说明该事件在注释里的影子定价用途,并给出回仓库自己核对的动作。
DeepSeek Harness 里四个都叫 version 的数字:0、15、8、1
DeepSeek Harness 仓库里有四个含义完全不同的版本号:会话格式 0、会话持久化 SQLite 15、会话查询 SQLite 8、通用 storage SQLite 1。本文按 2026-08-16 的仓库快照标出它们各自的常量名、所在文件与版本化的对象,并给出一套区分四条线的排查动作。
DeepSeek Harness 的 token 计量:文档两种 baseline,源码三元联合
DeepSeek Harness 的 token-meter 文档页只讲了 usage 与 estimated 两种 baseline,而源码里 TokenMeasurementBaseline 是三元联合,多一个 kind 为 none 的分支。本文把差异落到文件与行号,说清它何时产生、谁在读它,以及怎么自己核对。
DeepSeek Harness 的 spill:上下文放不下时溢出到哪、边界在哪
工具吐出几十万字节输出时,DeepSeek Harness 会把它写到磁盘、会话里只留头尾预览加一行引用。本文沿着 packages/spill 下三个包的源码,讲清 spill 的唯一开关 maxInlineBytes 从哪来、触发为何是严格大于、预览预算怎么被通知行先扣一刀,以及这条 seam 明确不做的事。
DeepSeek Harness 里的 TurnTrigger:文档还留着,packages 里搜不到
在 deepseek-harness 快照里查 TurnTrigger 这个类型名:三处子系统文档和两个生成脚本的映射表里都还写着它,而 packages 目录下所有 TypeScript 文件里一次都搜不到。本文给出可复现的检索动作、它现在还出现在哪几行、以及同一仓库里另外几处同类落差的核对方法。
工具体系、执行管线与权限审批
一次工具调用从 pre-execute 到落盘经过哪些阶段,审批为什么发生在 monotonic guards 之前。这一组还包括权限预设在源码默认表与出厂组合之间的档数差、README 与源码三处不一样的命名、bash 工具在限制型执行器下多出来的两个参数,以及一个我们没能在仓库里找到的东西——默认对普通工具发起 ask 的策略插件。
DeepSeek Harness 的工具调用管线:从 pre-execute 到结果落盘
DeepSeek Harness 把一次工具调用拆成了十九个节点。本文按仓库里的流程图与源码顺序走一遍这条管线,标出审批在何处插入、guard 为什么只能降权、结果被冻结在哪一步,以及目录文档与源码在 bash 参数上的一处口径差异,供你回仓库自查。
DeepSeek Harness 的审批顺序:为什么排在 monotonic guards 之前
DeepSeek Harness 的工具执行管线把用户审批排在 monotonic guards 之前。本文按仓库里生成的流程图分支边、子系统文档的 guard 类型定义与注册表源码行序读一遍这段顺序:人点过同意后为何还要再过一遍 guard,审批的四个取值各落到哪条分支,发起询问的来源只核到哪两处。
DeepSeek Harness 的权限预设有几档:源码两档、出厂组合三档
DeepSeek Harness 的权限预设有两份表:permission-presets 包的 Config 默认值是两档,出厂组合 cordis.patch.yml 里配的是三档。本文对齐两处的确切位置与字面值,说明 custom 为何不算一档、构造期哪两种配法会抛错,以及你自己怎么在仓库里核一遍。
DeepSeek Harness 的权限预设命名:README 与源码三处都不一样
DeepSeek Harness 的权限预设包里,事件名、斜杠命令名、settings 命名空间这三处,包 README 写的是 permissionPresets,而源码写的是 permission。本文逐处标出两边的文件与行号,给出可自己复核的检索动作,并说明为什么这三个名字值得逐个回源码核对。
DeepSeek Harness 的 bash 工具参数:目录五个,源码再展开两个
DeepSeek Harness 仓库自带的工具目录里,bash 工具的 JSON Schema 只列了五个参数;而源码里另有两个参数是条件展开的,只在挂载的执行器带沙箱模式时才加进 schema。本文沿着生成器口径与源码分支把这处差异讲清楚,并给出自己回仓库核对的具体动作。
DeepSeek Harness 的工具审批:没找到默认发起 ask 的策略插件
DeepSeek Harness 的工具管线里有 ask 决策、有审批服务、有四值封闭词表,但顺着源码找一圈,非测试代码里注册 tools/pre-execute 的七个文件中没有一个是通用询问插件。这篇记录查找动作、可复现的判定命令,以及仓库里 ask 的两个已知来源,供你回仓核对。
LLM 适配、流式与重试
模型接入这层被切成 adapter、provider 与手写路由。要注意的是供应商清单根本不在仓库里,唯一可读的证据是 Web golden 快照里的下拉选项。这一组把重试退避、抖动与流式空闲超时的默认值逐个落到常量行上,并说明为什么这套适配层的测试行数会比源码还多。
DeepSeek Harness 的模型接入分层:adapter、provider 与手写路由
顺着 DeepSeek Harness 仓库里 packages/llm 的源码走一遍模型接入层:ctx.llm 只管注册表与类型词汇,适配器只被要求实现一个 stream 方法,provider route 才是主键;再看目录路由与手写路由在协议、模型发现、模态声明上的分界线,以及凭据为什么不在这一层。
DeepSeek Harness 手写路由支持的三种线协议分别是什么
DeepSeek Harness 的 pi-ai 适配器里,手写 provider 的 api 字段只有三个合法取值。本文回到 provider.ts 的 PROTOCOLS 表,讲清这三个名字各自对应什么、顺序为何不随意、为什么 Bedrock 这类不在表里,以及它与模型发现、目录路由的关系。
DeepSeek Harness 支持哪些供应商:清单不在仓库,只有一份快照
想在 deepseek-harness 的源码里找出「它到底支持哪些模型供应商」,会发现这份清单压根不在仓库中——它来自一个未随仓提供的外部依赖。本文按快照 47f9438 梳理这条线索:清单从哪来、为什么读不到、仓库里唯一能直接读到的等价证据是哪个文件、那 36 个选项该怎么读,以及两处名单对不上的地方各在哪一行。
DeepSeek Harness 的重试与超时默认值:退避、抖动与流式空闲
DeepSeek Harness 的 LLM 重试与超时默认值只落在几处常量上:retry-policy.ts 的四个默认值加一份可重试错误码清单,超时由两个适配器各自的空闲常量控制。本文沿代码讲清退避公式、抖动系数、错误码来源、供应商 retry-after 的处置与配置该写在哪层,依据 2026-08-16 快照。
DeepSeek Harness 的 llm 包测试行数多于源码:适配层怎么测住的
在 deepseek-harness 快照 47f9438 里数 packages/llm:src 46 个文件 8040 行,tests 41 个文件 12349 行。本文给出可复现的统计口径,再沿源码讲清这层被测住的结构:封闭判别联合、七条适配器契约、三张 drift gate 清单、配置解析期的点名报错。
运行时与隔离:仓库自己说「这不是安全边界」
这一组是全专题最需要冷静读的一块。仓库在三处明写隔离不是安全边界;沙箱 schema 默认 read-only 而示例组合设的是 workspace-write;run_code 的 worker.terminate() 只结束线程、它 spawn 出去的进程会活下来;负责 glob/grep 的那个包 README 自称「the unconfined spawn」。
DeepSeek Harness 的隔离边界:仓库三处明写「这不是安全边界」
DeepSeek Harness 的 code-runtime、fs-sandbox 与 isolation 字段旁边,各有一句「不是安全边界」的原文。这篇把三处出处列出,再顺着 sandbox 的模式枚举、enforcement 取值与几条不过沙箱的执行路径,说清仓库自述的隔离词汇管到哪一层、哪些东西不在词汇表里。
DeepSeek Harness 的沙箱默认策略:schema 只读、示例可写工作区
DeepSeek Harness 的 sandbox-policy 在 schema 里把 mode 默认成 read-only,而 acp-agent 示例组合把同一字段设成 workspace-write 或 danger-full-access。本文标出两处位置,说清取值牵动哪些代码路径,以及如何核对生效值。
DeepSeek Harness 的代码执行残留:terminate 只结束线程
DeepSeek Harness 的 run_code 在 Node worker 线程里跑模型写的 TypeScript,computeMs 与 maxWallMs 到期都收敛到 worker.terminate(),而它只结束线程。本文回到源码标出这条限制的出处、它与 bash 路径进程组终止的差异,以及怎么判定。
DeepSeek Harness 的文件搜索:打包 ripgrep 与 unconfined spawn
DeepSeek Harness 的 glob 与 grep 不走 ctx.fs、也不注入 sandbox,而是 spawn 随包发布的 ripgrep 二进制。本文从 tool-fs-search 的 inject 读起,说清 README 里「unconfined」指什么、这条路径上还剩哪些约束、搜索上限是多少。
DeepSeek Harness 的 terminal 工具:README 说 pty,代码是 terminals
DeepSeek Harness 的 terminal-bash 插件,README 第 9 行写它注入 pty、sandboxPolicy、subprocess,src/index.ts 第 25 行的 inject 首项却是 terminals。并列两处原文,给出可自己核对的检索动作,并列出同仓其它几处同类差异。
扩展、编排与调度
写一个扩展并发布出去要遵守什么约定,skill 是什么格式,subagent 的六个 provider 里为什么只有两个能续接。这一组还包括 cookbook 写着 cron 表达式而协议里根本没有 cron、一个 README 说五个工具而源码注册七个的包,以及同一个轮次上限在包默认值与出厂组合里的两个数。
DeepSeek Harness 插件开发与发布:dsh-plugin 话题约定与官方流程
从写完一个 DeepSeek Harness 插件到别人能装上,中间隔着 bundle 与 profile 两个概念、四层配置叠加顺序,以及一条 git 安装的构建脚本陷阱。本文逐条对照仓库里的 publish 文档与 CLI 参考,说明 `dsh-plugin` 这个 GitHub 话题到底是约定还是机制。
DeepSeek Harness 的 Agent 轮次上限:包默认 256、出厂组合配 64
DeepSeek Harness 的 tool-ralph 在包源码里把 maxRounds 默认值写成 256,出厂组合的 cordis.patch.yml 里却配着 64。本文以此为线索,沿仓库文档记录的四层配置层叠顺序,说明一个默认值可能出现在几层、整行替换而非深合并意味着什么,以及看最终生效值该做哪个动作。
DeepSeek Harness 的 skill 是什么格式、怎么被装载
从 DeepSeek Harness 的 packages/skill/ 源码出发,讲清一个 skill 文件长什么样:目录 bundle 与扁平 Markdown 两种形态、frontmatter 必填项与两个 kebab-case 开关、六个发现根及其 rank 数值,附一份 skill 没被认到时的排查顺序。
DeepSeek Harness 的定时调度:文档写 cron,协议与源码里没有
DeepSeek Harness 的 extension-cookbook 机制表把定时任务一行写成 cron 语义,而 schedule 子系统文档与包 README 都写明协议里没有 Cron 表达式。本文标出这三处文件的具体位置,说明 schedule 协议实际支持哪三种规则,以及怎么自己动手核对。
DeepSeek Harness 的六个 subagent provider:只有两个能续接
DeepSeek Harness 有六个子代理 provider,按 2026-08-16 快照读源码,只有 spawn 与 fork 两个带 prepareContinuable。本文讲清两套并存的能力发现机制、可续接背后的 Session 与 Activation 结构,以及出厂组合实际配了哪几行。
DeepSeek Harness 注册了几个工具:README 五个、源码七个
DeepSeek Harness 的 tool-cordis 包,README 与源码有四处对不上:工具数五还是七、cordis_inspect 在源码里搜不到、服务键 ctx.dynamic 还是 dynamicCordisRunner、只在 README 出现的 ackTimeoutMs。本文逐条给出位置与行号。
子系统逐个读 · 会话、存储与设置
一次对话在磁盘上到底留下哪些东西,事件流怎么变成你看见的那个界面,历史会话怎么被翻出来,会话标题是谁起的,遥测记了什么。这一组把 storage、persistence、session-projection、session-query、telemetry、session-title、settings、workspace 八个包逐个读了一遍。
DeepSeek Harness 的会话持久化:一次对话在磁盘上留下哪些东西
顺着 deepseek-harness 仓库的源码走一遍会话落盘路径:目录根怎么解析、项目目录名怎么编码、日志文件叫什么、第一行 header 有哪些字段、事件什么时候才真正写进去、崩溃之后那半截轮次会被怎么处理,以及除了会话日志之外磁盘上还多出什么。
DeepSeek Harness 的存储层:storage 包统一了什么、又没统一什么
从一条 workspace 记录的写入出发,沿 deepseek-harness 仓库的 storage 家族走一遍代码路径,标出后端约定统一在哪一层,以及 json 与 sqlite 两个后端在配置字段、版本戳、耐久实现、错误码上各自岔开的位置,最后看装配文件里实际挂的是哪一个。
DeepSeek Harness 的会话投影:事件流怎么变成客户端看到的那个值
沿着 DeepSeek Harness 仓库里 session-projection 这条链路走一遍:一个 ProjectionDefinition 单元长什么样、注册表怎么把每个已提交事件折叠进每个单元、快照的 asOfSeq 从哪来、客户端为什么只认「seq 大的赢」,以及持久化投影缓存的两个强制写点与冷读阶梯。
DeepSeek Harness 的会话查询服务:历史会话是怎么被翻出来的
顺着 deepseek-harness 仓库 packages/session-query 下的源码走一遍:会话语料库怎么把 live 与持久化两个来源合成一条记录、全文搜索为什么在默认组合里是关闭的、哪些事件压根不会进索引,以及搜不到内容时该按什么顺序排查。
DeepSeek Harness 收不收数据:遥测子系统记了什么、记在哪、拿什么关
在公司机器上跑 dsh,会话内容会不会被传出去?顺着 deepseek-harness 仓库里 session-telemetry 这一对包的源码走一遍:默认 mode 为 DISABLED、DSH_TELEMETRY_DISABLED 任意非空值即硬关、一条记录带哪些字段、脱敏 waterfall 为何自带零规则。
DeepSeek Harness 的会话标题是谁起的:自动命名的触发时机与来源
会话列表里那行标题,在 DeepSeek Harness 里有三个可能的作者:确定性回退、注册的模型提供方、用户改名。本文沿着 packages/session/session-title 的代码路径走一遍,标出触发时机、字节上限、默认配置行与两条只写日志的事件,让你能自己回仓库里定位。
DeepSeek Harness 的设置分几层:用户设置的读取顺序与覆盖规则
顺着 DeepSeek Harness 仓库里 settings 子系统的代码路径走一遍:一个配置值要经过 schema 默认值、组合 base、用户文档三层,合并时对象递归、数组整体替换,删除只能走 replace 或 mutate。文中标出解析函数、默认文档路径与默认值,并按四个岔口给出改了没生效时的排查顺序,最后照实列出仓库自述的已知边界。
DeepSeek Harness 的工作区概念:workspace 划出来的那条线在哪
把 deepseek-harness 里的 workspace 注册表拆开看:它是宿主侧的一条持久记录,对模型完全不可见;会话属不属于某个工作区由「账本里有 id」加「header 的规范 cwd 相等」两个条件同时决定。沿源码走一遍成员资格、attach 拒绝路径、删除语义与两次写入的恢复标记,并标出文档与源码口径不一致的那一处。
子系统逐个读 · 执行、任务与不变式
一条 bash 命令从下发到回显走了哪几层,子进程的起管杀分别归谁,模型写的代码在哪儿跑,跑很久的活由谁托着。这一组还包括计划模式那条「不许动手」的线、goal 与计划模式的关系,以及一份写死在源码里的运行时不变式清单——那是他们把踩过的坑变成了断言。
DeepSeek Harness 的 Bash 执行器:一条命令从下发到回显的完整链路
顺着 deepseek-harness 仓库里 packages/shell/ 下的源码,把模型发出的一条 bash 命令从参数校验、工作目录解析、resolve 补默认值、交给 bash -c 落地,一直走到退出码标记被解析回退出状态的完整过程串一遍。途中逐个标出超时默认值与上限、每条流的输出上限、环境变量的三层合并顺序这些能直接回仓库查到的位置,也说清后台任务这条分叉、Windows 上换成哪一套,以及两处文档与源码对不上的口径。
DeepSeek Harness 的子进程管理:起、管、杀这三件事分别归谁
从「命令超时了,孙进程还活着」这个具体麻烦出发,沿着 DeepSeek Harness 的 subprocess seam 走一遍源码路径,说清楚 spawn spec 为什么一个默认值都不给、terminate() 为什么是唯一的终止动词、以及超时判定为什么被刻意留在调用方手里。
DeepSeek Harness 的代码运行时:模型写的代码在哪儿跑、能碰到什么
顺着 DeepSeek Harness 仓库里 run_code 的调用链走一遍,说明模型写的那段程序被塞进哪个 worker、看得到哪些全局对象、被哪两个预算掐掉、超出输出上限会得到什么结果,以及仓库自己承认的边界在哪里。
DeepSeek Harness 后台任务运行时:ctx.jobs 怎么托住一个跑很久的活
一次 20 分钟的后台命令,工具调用早就返回了,是谁还记着它、谁负责杀它、结果又怎么回到模型手里。本文顺着 deepseek-harness 仓库里 packages/jobs 三个包的源码走一遍:start 的预检顺序、每 owner 默认 10 个的并发闸、settle 的先来先赢、以及完成通知那条 wakeup 预算为 3 的链路。
DeepSeek Harness 的 workflow 包:它跟 Agent 自己规划有什么不一样
同样是把活拆给一堆 subagent,让模型一轮一轮委派和让模型写一段编排脚本,在 DeepSeek Harness 里走的是两条完全不同的路径。本文沿着 packages/workflow 下的四个包读一遍:脚本在哪校验、并发上限怎么算出来、取消之后谁负责收尸,以及哪些默认值只是默认值。
DeepSeek Harness 的计划模式:进入、退出与「不许动手」的边界
从一次 /plan 命令出发,沿 dsh-plan-mode 的源码走完进入、待生效、追加、退出的整条路径,标出 plan/mode 事件、order 50 的 plan:policy 段落、exit_plan_mode 的标题正则等具体位置,并说清「不许改文件」这句约束到底由谁执行。
DeepSeek Harness 的「同会话目标」:goal 是什么、跟计划模式是什么关系
从「会话恢复后它还会不会自己接着干」这个问题出发,沿 packages/goal 走一遍:四个持久 phase 与 armed/disarmed 两态怎么分工、一个 Goal Round 由谁放行、defaultMaxGoalRounds 256 与 blockedAfterConsecutiveRounds 3 这两个默认值分别管什么,以及 goal 与 plan mode 在源码里到底有没有关系。
DeepSeek Harness 的运行时不变式:一份写死的「不许出现」清单
从一条没有配对的授权事件出发,沿 DeepSeek Harness 的 invariants 注册表源码走一遍:Config 三个字段各自的默认值、包名正则不锚定与配置写错就启动失败的坑、包名被提前保留的语义、219 个工作区包里只有 35 个可执行检查,以及标准组合实际只挂了 4 个这件事,顺带记一处文档与源码的数量差异。
子系统逐个读 · 交互、凭据与提示词
审批弹窗是谁发起谁应答、拒绝之后会怎样,AskUserQuestion 这条反问用户的路怎么铺,斜杠命令从注册到执行的一条线,模型跑着的时候你插一句话会发生什么。这一组还包括 API Key 存在哪、一张图怎么落盘、系统提示词是按什么顺序拼出来的。
DeepSeek Harness 的用户审批是怎么弹出来的:谁发起、谁应答、拒绝之后发生什么
沿着 DeepSeek Harness 仓库里 ctx.approval 的调用路径走一遍:一次工具调用在哪一步变成审批请求、never 策略在哪里被提前判掉、四种 outcome 分别映射成什么拒绝文案,以及没有任何应答者时为什么结果是拒绝而不是放行。
DeepSeek Harness 的「反问用户」:ask_user_question 这条路是怎么铺的
从模型看到的 ask_user_question 参数表出发,沿着 tool-ask-user、ctx.userQuestions 和 Web 宿主 provider 走一遍,标出 ask() 的五道闸门、九个错误码的出处、plan-review 意图的认领条件,以及回答批次在宿主侧要过的逐条校验。
DeepSeek Harness 的用户命令系统:斜杠命令从注册到执行的一条线
从输入框里敲下的一行斜杠命令出发,沿着 deepseek-harness 仓库的代码路径走一遍:解析正则怎么划边界、注册时校验哪些字段、command/run 与 command/done 这对日志在什么时刻落盘、取消信号能管到哪里,以及为什么命令的输出不会进入模型上下文。
DeepSeek Harness 的消息反馈通道:模型跑着的时候你插一句 /feedback 会怎样
从「模型正在跑,我打一句反馈会不会打断它、会不会被模型看见」这个问题出发,沿 DeepSeek Harness 仓库里 feedback 家族的两条通道走一遍代码路径,落到 recordFeedback、recordInput、maxNoteBytes、ifVersion 这些具体字段与默认值上,并如实标出文档与源码口径不一致的两处。
DeepSeek Harness 怎么存一张图:持久图片附件的落盘、引用与清理
沿着 DeepSeek Harness 仓库里 attachment 这条路走一遍:一张图从提交到落盘要过几道准入检查、四个默认上限分别是多少、引用里到底存了什么、读回时怎么校验,以及为什么"删会话"并不等于"删图"。全部依据仓库源码与子系统文档,不含任何本机运行结论。
DeepSeek Harness 把你的 API Key 放在哪:凭据子系统的存取与作用域
从一次模型请求取 key 的调用路径出发,沿 DeepSeek Harness 的 credentials seam 与本地提供方走一遍:四层来源的优先级、set 为什么会被环境变量挡回来、`.credentials.yaml` 的严格格式与 0600 权限检查,以及仓库自己写明的安全边界与已知限制。
DeepSeek Harness 的扩展体系:packages/extensions 里到底装了什么
从「模型自己写一个插件、当场装进正在运行的进程」这条路径出发,沿 deepseek-harness 仓库的 packages/extensions 走一遍:四个包各自的分工、cordis_define 到 node:vm 的调用链、vmTimeoutMs 默认 5000 的确切含义,以及 README 与源码对不上的三处口径差异。
DeepSeek Harness 的系统提示词是拼出来的:order 数值、可插入的位置与几处撞车
想给 dsh 插一句自己的提示词,order 该填几?本文沿着 assemble 到 renderPrompt 的调用路径,把仓库里三十处 section 注册的真实 order 数值、五个插入口、严格插值规则,以及 105、106、115、190 上的四处同序撞车逐一标出来。
子系统逐个读 · 网络、流式与语言服务
dsh web 起来之后都开了哪些口,一个 token 到屏幕上要经过几层,接进来的 LSP 给 Agent 带来了什么又限制了什么,以及他们为什么要自己写一套叫 Typert 的远程调用。
DeepSeek Harness 的 HTTP 服务器:dsh web 起来之后都开了哪些口
从浏览器打开本地页面这一个动作出发,沿 deepseek-harness 仓库的源码走一遍:谁在监听、监听在哪个地址、路径按什么顺序匹配、shipped Web 组合里到底注册了哪几条具名路由与 upgrade 路径,以及 fallback 席位的四条固定语义分别落在哪一行代码上。
DeepSeek Harness 流式输出:一个 token 到屏幕上要经过几层
沿着 deepseek-harness 仓库的代码路径,把模型吐出的一个字从 SSE 字节到浏览器渲染之间经过的每一层拆开:SSE 解析、chunk 翻译、空闲 watchdog、llm/stream waterfall、agent loop 的双写、日志打包、推送帧与客户端二次折叠,逐层标出文件与默认值。
DeepSeek Harness 接了 LSP:语言服务给 Agent 带来了什么、又限制了什么
沿着 DeepSeek Harness 仓库里 lsp 工具的调用路径走一遍:一基坐标在哪一行转成零基、workspace 从哪里取、进程按什么粒度池化、结果被哪两个默认值截断,以及这条链路明确不做的那几件事。
DeepSeek Harness 的 Typert:一套自己写的远程调用是为了解决什么
从「Host 上新加一个方法、怎么让浏览器端调到它」出发,沿 DeepSeek Harness 仓库里的 Typert 代码路径走一遍:装饰器标记存在哪、InvocationDescriptor 有哪些字段、lookup 参数怎么换成 wire 字段、取消信号为什么不进 args,以及 hasSeen 这个边界。
架构总纲:几张自动生成的全局表
host、client、runtime 三段是怎么切的,哪个包被依赖得最狠、哪个是叶子,所有能配的项在哪张表里,往磁盘写了多少种东西,一次工具调用从模型出参到结果回填的完整管线。最后一篇是他们把踩过的坑写成的编码约定。
DeepSeek Harness 架构全图:host、client、runtime 这三段到底切在哪一刀
很多人拿到 deepseek-harness 会先按目录名把它理解成 host、client、runtime 三层。翻过源码就会发现这条线不是按目录走的:真正的硬切只有两个 face,写在 tsconfig.json 和 tsdown.config.ts 里,而且它是从包内部穿过去的。本文沿这条线走一遍,标出关键文件与数值。
DeepSeek Harness 的模块依赖图:哪个包被依赖得最狠、哪个是叶子
从 docs/module-graph.md 这张生成图出发,数清 packages/*/* 下 219 个包与 1089 条边,找出唯一叶子 invariants,对比「直接入度」与「传递影响面」两张榜为什么排序不同,并指出这张图只读 peerDependencies、看不见 bundle/base 那 75 条 dependencies 边的口径边界。
DeepSeek Harness 的配置目录:所有能配的项都在这张自动生成的表里
docs/config-catalog.md 是脚本从源码生成并有校验闸门的配置总表。本文从「想改一个超时值该去哪查」出发,说明这张表收了哪 105 个包、三类没收进来的包在哪、默认值为什么常常不在表里,以及 cordis.yml 与 settings.yaml 两条配置轴的关系。
DeepSeek Harness 到底往磁盘写了多少种东西:持久化目录逐条看
一次对话结束后本机上留下了什么?本文按 deepseek-harness 仓库的持久化事件目录与 packages/storage 源码,数清会话日志的 44 种事件类型、磁盘上另外 4 种非事件行标签,以及非会话存储的三个领域、两个后端各自的落盘方式与版本号。
DeepSeek Harness 的工具执行管线全图:从模型出参到结果回填
模型吐出一个 tool-call 块之后、会话日志里出现 tool/result 之前,DeepSeek Harness 里到底经过了几道关口。本文沿 packages/core/tools 的源码走一遍:参数冻结、pre-execute、单调守卫、审批、环绕分发、post-execute、finalizeContent,并标出 ABORTED 与 TOOL_TIMEOUT 这些错误码分别在哪一层产生。
DeepSeek Harness 的防御式模式:他们踩过的坑写成了编码约定
DeepSeek Harness 仓库里有一份只有几百词的 defensive-patterns 文档,七条规则按文档自述全是这个项目实际发布过或差点发布出去的缺陷。这篇沿着一条 bash 命令的超时结果往下走,把这七条规则逐条对回 packages 下的实现:ShellRunResult 的字段为什么拆成那样、3000 毫秒的 graceMs 写在哪一行、环境变量清理的正则长什么样、spill 文件为什么要随机名加 0o600 打开。
动手改它:官方 cookbook 逐篇拆
给它加一个工具、加一个 workspace 包、接一个新模型、塞一个 vendored 包、给 Web 端加一个会话节点,各自要动哪些文件、遵守哪些约定。这一组还包括他们自己那个代码评审 skill 怎么维护,以及团队在堆叠 PR 上怎么回应评审意见。
给 DeepSeek Harness 加一个工具:官方工具编写参考逐步拆
从二十几行的最小工具出发,沿着 defineTool 与注册表的代码路径走一遍:output 为什么是必填、timeoutMs 被校验了两次、presentCall 校验失败为什么不抛异常、后台任务发布 id 之后该听谁的取消信号,以及工具目录的完整性守卫怎么防止新工具漏文档。
给 DeepSeek Harness 加一个 workspace 包:官方实操手册在管什么
照着 docs/cookbook/adding-a-package.md 建一个新包,很容易在 pnpm run constraints 这一步栽跟头。本文沿着 scripts/check-workspace-constraints.ts 的判断顺序,把这份手册里哪几条是脚本会真的拦你、哪几条与仓库实况对不上,逐条落到具体文件、行号与数值上。
给 DeepSeek Harness 接一个新模型:LLM 适配器怎么写
从「我要接一个自家网关」这个具体需求出发,沿 DeepSeek Harness 仓库的 packages/llm 走一遍:什么时候只改配置就够、什么时候得写适配器包、registerAdapter 会在哪几行把你的注册打回来、StreamChunk 那几条协议义务落到参考实现的哪一段代码上,以及密钥与默认值的口径。
给 DeepSeek Harness 塞一个 vendored 包:为什么要这么麻烦
从「我想再引一个上游 Cordis 插件」这个具体需求出发,沿着 deepseek-harness 仓库里 vendor/ 的复制、改 scope、注册进两处 tsconfig、过 pre-commit 守卫和 hygiene 检查的路径走一遍,标出每一步落在哪个文件的哪个字段,并列出 cookbook 与源码口径对不上的三处。
给 DeepSeek Harness 的 Web 端加一个会话节点:前端这条链怎么接
想在 dsh 的 Web Chat 流里插一行自己的业务内容,官方 cookbook 只给了实现路径。本文顺着 Definition 注册、Assembler 装配、Chat 快照排序这条链把关键文件和写死在代码里的约束逐个标出来,包括那几条会直接抛异常的规矩。
DeepSeek Harness 的扩展开发手册:一个扩展的完整生态位
顺着 deepseek-harness 仓库里的扩展手册与 packages/extensions 源码走一遍,看清一个扩展从「挑哪种形态」到「挂在哪个扩展点」再到「运行时能不能看见它」的完整位置,并逐处标出文档与源码对不上的地方。
DeepSeek Harness 的 dsh-code-review skill 是怎么维护的
团队里那份代码评审提示词写完就没人动过,是很常见的结局。DeepSeek Harness 把自己的 dsh-code-review skill 交给一套周期维护流程,本文沿着仓库里的 cookbook、Agent Note 与门禁脚本走一遍:文件在哪、谁改它、采纳证据怎么算、哪几道门禁真的读到了它,以及文档自己标出来的未完成部分。
DeepSeek Harness 团队怎么在堆叠 PR 上回应评审意见
评审意见落在依赖堆叠的中间那一层时,改哪一层、怎么往上传、推送之后凭什么说这条意见还处于已解决状态,都容易做反。这篇沿着 deepseek-harness 仓库里的堆叠评审指南、堆叠落地 skill 与推送前 skill 走一遍,把五条基本规则、七个处置步骤对应到 `gh stack` 命令与 `scripts/change-scope.ts` 里的具体校验,包括 worktree 隔离、lease 保护推送、同步后立即验证这几处,也照实标出仓库文档没有说明的部分。
事故复盘:四份真实案卷
一个 default export 让依赖注入静默失效、一个 JS 表达式把文件系统工具全禁掉、Web Agent 自己跟自己形成反馈闭环、Landlock 的部分强制执行被误判成子进程失败。四份复盘加一篇讲他们把哪些事写成案卷、案卷该怎么写——这是全专题最能看出工程习惯的一块。
DeepSeek Harness 的事故复盘制度:他们把哪些事写成了案卷
deepseek-harness 把 bug 故事单独关在 docs/postmortem 一个目录里,全站其余文档明令禁止叙事。本文沿 docs/AGENTS.md 的分层表、postmortem/README.md 的准入三条件和四份案卷的实际节序走一遍:什么样的 bug 才配写成案卷,时间线为什么锚事件序号,防护措施为什么必须落到能在树里翻到的文件,以及案卷里有一条口径已经和今天的源码对不上了。
一个 export default 让依赖注入失效:DeepSeek Harness 的 ACP 事故完整还原
DeepSeek Harness 仓库里有一份编号 0001 的事故复盘:ACP 服务器在编辑器连上的一瞬间崩溃,报错是「拿不到 agents,因为没有 inject」。本文沿着 Loader 的 unwrapExports、Cordis 的 fiber 遍历一路走到 AgentLoop.resume,标出每一处能自己回仓库核的文件与行号,并对照今天源码里还剩下什么守卫。
一个 !!js 表达式把文件系统工具全禁掉了:DeepSeek Harness 0002 号复盘
DeepSeek Harness 仓库里 0002 号事故复盘讲的是:一行写在 disabled 上的 !!js 表达式没有被求值,read/write/edit 三个工具在所有模式下都没注册,而快照测试却全绿。本文沿着配置、Loader 语义、守卫脚本走一遍,并指出复盘文档与当前仓库口径不一致的两处。
Web Agent 自己跟自己较劲:GUI 反馈闭环那次事故
DeepSeek Harness 仓库里的 postmortem 0003 记录了一次 Web agent 改完 GUI 源码却验收错对象的事故。本文沿着它的修复路径读源码,把 window.__DSH_BOOT__ 注入点、apps/web 拒启动的那一行、app:web-surface 提示词区段和 DSH_WEB_URL 变量逐个落到文件上,并指出文档口径与当前代码不一致的两处。
Landlock 部分强制执行被误判:0004 号事故与沙箱归因的真实边界
DeepSeek Harness 的 0004 号事故复盘里,一条无害的 Landlock 通知行让 ripgrep「没搜到」被报成沙箱不可用。本文沿 launcher 契约、RunnerFailureRule 三字段与 classifyRunnerFailure 的判定顺序走一遍代码路径,标出退出码 125 与 127,并说明哪些后端仍只靠签名匹配。
横向对照:Claude Code、Codex 与 Pi
同一件事各家怎么做:skill 的装法与触发、权限预设与审批时机、沙箱走 Landlock 还是 bwrap 还是容器、上下文压缩会让你丢失什么、子代理的派生与回收、扩展机制、AGENTS.md 与 CLAUDE.md 的读法、想换个模型供应商各要改哪一层。只对照双方都白纸黑字写明的机制,一方查不到就明说不比;Claude Code 闭源,只用官方文档、不推断实现。三家不排名。
四家的 skill 都叫 skill,装法和触发完全不是一回事
同一个 SKILL.md 目录搬到 DeepSeek Harness、Claude Code、Codex、Pi 四家会遇到四类差异:放在哪才被发现、同名谁赢、谁能触发、加载进上下文之后是什么形态活多久。本文只对照四方公开写明的机制,逐条标出文件与数值,不排名。
权限与审批模型对照:预设怎么定、什么时候弹、拒绝之后怎么走
把 DeepSeek Harness 的沙箱模式与审批策略两个旋钮、Claude Code 官方文档写明的六步判定顺序、Codex 仓库里的 AskForApproval 与 execpolicy 三档判定、以及 Pi 自述没有权限弹窗的设计,放在同一条决策路径上对照,说清各自把边界划在哪、拒绝之后这次调用变成什么。
沙箱与隔离对照:Landlock、Seatbelt 与容器,三条路各自守住了什么
同一条命令跑在本机上,谁来拦、拦不住时会怎样?把 DeepSeek Harness 的 packages/sandbox、Claude Code 官方文档写明的 Bash 沙箱、Codex 仓库里的 bwrap 与 seccomp、Pi 文档自述的「没有内置沙箱」放在一起,只比四方都白纸黑字写明的机制,落到具体文件、具体默认值和具体退出码上。
上下文压缩对照:DeepSeek Harness、Claude Code、Codex、Pi 各自压掉了什么
从「什么时候触发压缩、保留哪一段、切在哪个边界、摘要留下什么字段」四条线索,把 DeepSeek Harness 的 packages/compaction、Claude Code 官方文档写明的压缩后存活表、Pi 的 compaction 文档、Codex 仓库里的配置键放在一起读,指出各自把边界划在哪里以及这些差异什么时候会咬到你。
子代理对照:派生、隔离与回收,DeepSeek Harness 与三家的边界差在哪
子代理跑飞了谁来收?本文只对照 DeepSeek Harness、Claude Code、Codex、Pi 四方公开写明的机制,把派生时孩子继承什么、递归深度默认几层、并发额度怎么占、活干完谁负责释放这四件事逐一落到具体文件与默认值上,并指出配置期就会炸的那一处。
扩展机制对照:Cordis 插件、Pi extensions 与 Claude Code 的 hooks/plugins
同一个诉求——在工具调用落地前拦下它、顺手改掉入参——在 DeepSeek Harness、Pi 与 Claude Code 里要写的东西完全不同。本文沿着 packages/hooks 的桥接映射表、Pi 的 tool_call 契约与 Claude Code 官方文档的退出码规则各走一遍,标出三家各自把边界划在哪一行。
AGENTS.md 与 CLAUDE.md:同一份项目说明书,四个工具的读法都不一样
同一个仓库里放一份项目说明书,DeepSeek Harness、Claude Code、Codex、Pi 读出来的东西并不相同。本文按各自公开的源码与官方文档,逐一核对文件名候选、向上遍历到哪一层停、子目录何时加载、字节预算多大,并指出这些差异在 monorepo 里会从哪里咬到你。
模型接入分层对照:想换个供应商,各家要你改哪一层
同样是把模型换成另一家,DeepSeek Harness、Codex、Pi、Claude Code 要你动的层完全不同——有的改一段 YAML,有的改 TOML,有的得写一个插件包,有的只让你改端点不让你换模型。本文沿各自公开的配置结构走一遍,标出关键文件、字段与默认值。
想把 Agent 框架真正读懂、而不是停在 README?
站内有成体系的 AI 编程与 Agent 工程学习路线,从工具配置一路到架构落地。