DSH plugin 交付物怎么声明:present、PresentedFile 与改动摘要
DSH plugin 的「交付物」其实是两条独立通道:一条是模型通过 present 工具主动声明的文件,另一条是这一轮实际被改动的文件。 前者靠工具调用记录,后者靠 git 工作树在轮开始与轮结束的快照对比;git 覆盖不到的路径,则由文件工具每次编辑前后的整文件捕获补上。两条通道都用只写日志的事件宣告,但关键区别在于:摘要本身不在日志里,而是由 Host 服务在 Session 存活期间按事件序号提供。
这解释了一个常见现象——Host 重启后重新打开旧会话,先前轮次的改动卡片就没了。
DSH plugin 交付物的两条通道:声明与改动
一句话结论:present 管「我交付了什么」,workspace/changes 管「这一轮改了什么」,二者不能互相替代。
| 通道 | 触发 | 记录方式 | 内容 |
|---|---|---|---|
| present 声明 | 模型调用 present 工具 | 只写日志的 deliverables/presented | 文件路径与描述 |
| 轮次改动 | 顶层轮停止 | 只写日志的 workspace/changes | 事件只宣告轮次,摘要由 Host 提供 |
- 两条都只读:客户端读取并在轮末渲染,服务端不据此修改模型上下文。
- 互不覆盖:声明了但没改的文件只出现在 presented 里;改了但没声明的只出现在改动摘要里。
- 别把事件当数据:
workspace/changes只带turn,要摘要得再调 Host 服务。
DSH plugin 的 PresentedFile:present 声明落在事件里
一句话结论:每次 present 成功追加一条事件,记录轮次、调用 id 与文件列表;文件内容仍留在原路径。
interface PresentedFile {
path: string // 绝对路径,或相对会话工作目录
description?: string
}
- 写入时机:present 的最终结果成功时才追加
deliverables/presented,失败不记录。 - 内容不搬走:声明只登记路径,文件仍在源路径,消费方按此渲染或打开。
- 一条事件一次调用:
{ turn, callId, files },callId 对应模型的这次工具调用。 - 适合什么:报告、截图、导出的表格——「请用户查看这个产物」的场景。
- 不适合什么:想表达「我改了哪些文件」用改动摘要,不要用 present 硬凑。
DSH plugin 改动摘要的来源:git 快照加整文件捕获
一句话结论:有 git 就用轮开始/结束的工作树快照,没有就用文件工具的编辑前后捕获,两路合并成一份摘要。
- git 路径:对比轮开始与轮结束的工作树快照,得出改动文件与增删行数。
- 非 git 路径:文件工具每次编辑前后的整文件捕获,补上 git 覆盖不到的改动。
- 展示标签
display:工作目录内用相对路径,仓库上方用../,家目录下用~,其余用绝对路径,统一斜杠分隔。 - 特殊标记:
binary表示 git 判定二进制或捕获侧含 NUL 字节;oversized表示某一侧超过maxFileBytes,只列文件不给行数。 - 上限:
files按display排序并按maxFiles截断;total、added、deleted仍统计全部文件,包括被截断的。 - 快照标识:
snapshot.before与snapshot.after是两次 git 树 id,没取快照时缺省。
DSH plugin 的摘要获取:summary 与 diff
一句话结论:摘要不在日志,按事件序号向 Host 服务要;对比按文件下标现算,Session 释放后就没有了。
const summary = ctx.workspaceChanges.summary(sessionId, seq)
const diff = await ctx.workspaceChanges.diff(sessionId, seq, index, signal)
- summary 的条件:该 Session 仍存活、且这个 Host 记录过该事件;否则返回
undefined。 - diff 的输入:事件序号加文件在
files里的下标,返回文本、二进制或超限三种结果之一。 - 文本对比的形状:
hunks按文件顺序,两侧相同则为空数组;比较超时会让coarse为 true,所有行按替换展示。 - 二进制与超限:没有行内容,只有
path与display。 - 失败语义:存活会话的快照读取失败会抛错,而不是返回空对比。
DSH plugin 的事件边界:不进模型请求,重启即丢摘要
一句话结论:两个事件都不进入模型请求;摘要依赖 Host 存活,这是设计边界而不是 bug。
- 模型看不到:
deliverables/presented与workspace/changes都不会进入模型请求。 - 轮末渲染:Web 的产出物插件在轮末统一渲染声明与改动两类。
- 重启边界:Host 重启后重新打开旧会话,先前轮次的改动卡片消失——摘要从未写进日志。
- 同轮覆盖:同一轮里后来的事件替代先前的,客户端只保留最新一条。
- 需要长期留存就自己存:把 summary 复制到你自己的存储(例如 StorageBackend),不要指望它一直在。
DSH plugin 排查注意事项
一句话结论:交付物问题先分「没记录」「记录在但摘要空」「重启后没了」三类。
- 声明了没显示 → 检查 present 的最终结果是否成功,失败时不会追加事件。
- 改了文件但列表空 → 确认改动发生在顶层轮内,并检查是否超出
maxFiles。 - 行数缺失 → 文件被标记为 binary 或 oversized。
- 摘要是 undefined → Session 已释放,或这个 Host 没记录该事件。
- 对比展示全为替换 →
coarse为 true,行比较超过diffTimeoutMs。 - 修复状态如实:本文的两条通道、字段定义、摘要提供方式与重启边界均取自官方「产出物」页面与两个包的 README;配置项(
maxFiles、maxFileBytes、diffTimeoutMs)以对应包文档为准。
常见问题
不是,DSH plugin 的交付物有两条独立通道:present 声明的是模型主动交付的文件,改动摘要是这一轮实际被修改的文件。前者靠工具调用记录,后者靠 git 快照与文件工具整文件捕获,两者互不替代。
DSH plugin 的 workspace/changes 事件只在日志里宣告「这一轮有改动」,摘要本身由 Host 服务在 Session 存活期间按事件序号提供。Host 重启后重新打开旧会话,先前轮次就没有改动卡片了。
DSH plugin 对 git 覆盖不到的路径,用文件工具每次编辑前后的整文件捕获来算增删行数。两条来源合并进同一份摘要,所以不在仓库里的文件也能出现在改动列表里。
DSH plugin 的改动文件里,binary 表示 git 判定为二进制或捕获侧含 NUL 字节,oversized 表示某一侧超过插件的 maxFileBytes。两者都只列出文件,不提供行数或对比内容。
DSH plugin 的同一轮里后来的事件会替代先前的,客户端只保留最新一条。因此不要依赖事件数量判断改了几次,摘要里的 total 才是完整改动文件数。
相关术语
- PresentedFile(声明的交付文件)
- PresentedFile 是模型通过 present 工具声明交付的文件,含路径与可选描述,文件内容仍留在原路径。它记在一个只写日志的会话事件里。— https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/deliverables.zh.md
- WorkspaceChangedFile(改动文件)
- WorkspaceChangedFile 描述一轮内被修改的一个文件,含相对路径、展示用标签、增删行数与可选的 binary、oversized 标记。行数来自 git 或文件工具的整文件捕获。— https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/deliverables.zh.md
- WorkspaceChangesSummary(改动摘要)
- WorkspaceChangesSummary 是一轮顶层对话的改动汇总,含轮次、cwd、按展示顺序排列的文件、完整计数与增删总量,以及可选的 git 树快照标识。它不在事件日志里,由 Host 服务提供。— https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/deliverables.zh.md
- WorkspaceDiffHunk(对比块)
- WorkspaceDiffHunk 是一个带三行上下文的 unified diff 块,记录新旧起始行与行数,正文每行保留 +、- 或空格前缀。多个块组成一个文件的文本对比。— https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/deliverables.zh.md
来源
- DeepSeek Harness 文档 — 产出物(PresentedFile、WorkspaceChangesSummary、提供摘要与对比)· deepseek-ai(GitHub)
- tool-present 包 README(present 工具行为与配置)· deepseek-ai(GitHub)
- workspace-changes 包 README(快照机制与上限配置)· deepseek-ai(GitHub)