DSH plugin 交付物怎么声明:present、PresentedFile 与改动摘要

插件开发发布于 2026-10-17作者: DeepSeek Plugin 插件市场
DeepSeek HarnessDSH pluginPresentedFilepresent改动摘要deliverables
DSH plugin 的交付物有两条通道:present 工具声明的文件,以及一轮内的改动摘要。两者都是只写日志的事件,摘要由 Host 服务按事件序号提供,不进日志也不进模型请求。

DSH plugin 的「交付物」其实是两条独立通道:一条是模型通过 present 工具主动声明的文件,另一条是这一轮实际被改动的文件。 前者靠工具调用记录,后者靠 git 工作树在轮开始与轮结束的快照对比;git 覆盖不到的路径,则由文件工具每次编辑前后的整文件捕获补上。两条通道都用只写日志的事件宣告,但关键区别在于:摘要本身不在日志里,而是由 Host 服务在 Session 存活期间按事件序号提供。

这解释了一个常见现象——Host 重启后重新打开旧会话,先前轮次的改动卡片就没了。

DSH plugin 交付物的两条通道:声明与改动

一句话结论:present 管「我交付了什么」,workspace/changes 管「这一轮改了什么」,二者不能互相替代。

通道触发记录方式内容
present 声明模型调用 present 工具只写日志的 deliverables/presented文件路径与描述
轮次改动顶层轮停止只写日志的 workspace/changes事件只宣告轮次,摘要由 Host 提供
  1. 两条都只读:客户端读取并在轮末渲染,服务端不据此修改模型上下文。
  2. 互不覆盖:声明了但没改的文件只出现在 presented 里;改了但没声明的只出现在改动摘要里。
  3. 别把事件当数据:workspace/changes 只带 turn,要摘要得再调 Host 服务。

DSH plugin 的 PresentedFile:present 声明落在事件里

一句话结论:每次 present 成功追加一条事件,记录轮次、调用 id 与文件列表;文件内容仍留在原路径。

ts
interface PresentedFile {
  path: string          // 绝对路径,或相对会话工作目录
  description?: string
}
  1. 写入时机:present 的最终结果成功时才追加 deliverables/presented,失败不记录。
  2. 内容不搬走:声明只登记路径,文件仍在源路径,消费方按此渲染或打开。
  3. 一条事件一次调用:{ turn, callId, files },callId 对应模型的这次工具调用。
  4. 适合什么:报告、截图、导出的表格——「请用户查看这个产物」的场景。
  5. 不适合什么:想表达「我改了哪些文件」用改动摘要,不要用 present 硬凑。

DSH plugin 改动摘要的来源:git 快照加整文件捕获

一句话结论:有 git 就用轮开始/结束的工作树快照,没有就用文件工具的编辑前后捕获,两路合并成一份摘要。

  1. git 路径:对比轮开始与轮结束的工作树快照,得出改动文件与增删行数。
  2. 非 git 路径:文件工具每次编辑前后的整文件捕获,补上 git 覆盖不到的改动。
  3. 展示标签 display:工作目录内用相对路径,仓库上方用 ../,家目录下用 ~,其余用绝对路径,统一斜杠分隔。
  4. 特殊标记:binary 表示 git 判定二进制或捕获侧含 NUL 字节;oversized 表示某一侧超过 maxFileBytes,只列文件不给行数。
  5. 上限:files 按 display 排序并按 maxFiles 截断;total、added、deleted 仍统计全部文件,包括被截断的。
  6. 快照标识:snapshot.before 与 snapshot.after 是两次 git 树 id,没取快照时缺省。

DSH plugin 的摘要获取:summary 与 diff

一句话结论:摘要不在日志,按事件序号向 Host 服务要;对比按文件下标现算,Session 释放后就没有了。

ts
const summary = ctx.workspaceChanges.summary(sessionId, seq)
const diff = await ctx.workspaceChanges.diff(sessionId, seq, index, signal)
  1. summary 的条件:该 Session 仍存活、且这个 Host 记录过该事件;否则返回 undefined。
  2. diff 的输入:事件序号加文件在 files 里的下标,返回文本、二进制或超限三种结果之一。
  3. 文本对比的形状:hunks 按文件顺序,两侧相同则为空数组;比较超时会让 coarse 为 true,所有行按替换展示。
  4. 二进制与超限:没有行内容,只有 path 与 display。
  5. 失败语义:存活会话的快照读取失败会抛错,而不是返回空对比。

DSH plugin 的事件边界:不进模型请求,重启即丢摘要

一句话结论:两个事件都不进入模型请求;摘要依赖 Host 存活,这是设计边界而不是 bug。

  1. 模型看不到:deliverables/presented 与 workspace/changes 都不会进入模型请求。
  2. 轮末渲染:Web 的产出物插件在轮末统一渲染声明与改动两类。
  3. 重启边界:Host 重启后重新打开旧会话,先前轮次的改动卡片消失——摘要从未写进日志。
  4. 同轮覆盖:同一轮里后来的事件替代先前的,客户端只保留最新一条。
  5. 需要长期留存就自己存:把 summary 复制到你自己的存储(例如 StorageBackend),不要指望它一直在。

DSH plugin 排查注意事项

一句话结论:交付物问题先分「没记录」「记录在但摘要空」「重启后没了」三类。

  1. 声明了没显示 → 检查 present 的最终结果是否成功,失败时不会追加事件。
  2. 改了文件但列表空 → 确认改动发生在顶层轮内,并检查是否超出 maxFiles。
  3. 行数缺失 → 文件被标记为 binary 或 oversized。
  4. 摘要是 undefined → Session 已释放,或这个 Host 没记录该事件。
  5. 对比展示全为替换 → coarse 为 true,行比较超过 diffTimeoutMs。
  6. 修复状态如实:本文的两条通道、字段定义、摘要提供方式与重启边界均取自官方「产出物」页面与两个包的 README;配置项(maxFiles、maxFileBytes、diffTimeoutMs)以对应包文档为准。

来源:产出物、tool-present README、workspace-changes README。

常见问题

DSH plugin 里 present 声明的文件和「这一轮改了什么」是一回事吗?

不是,DSH plugin 的交付物有两条独立通道:present 声明的是模型主动交付的文件,改动摘要是这一轮实际被修改的文件。前者靠工具调用记录,后者靠 git 快照与文件工具整文件捕获,两者互不替代。

DSH plugin 里,为什么一轮的改动摘要不在会话日志里,重启后就看不到了?

DSH plugin 的 workspace/changes 事件只在日志里宣告「这一轮有改动」,摘要本身由 Host 服务在 Session 存活期间按事件序号提供。Host 重启后重新打开旧会话,先前轮次就没有改动卡片了。

DSH plugin 里,git 覆盖不到的路径,改动是怎么算出来的?

DSH plugin 对 git 覆盖不到的路径,用文件工具每次编辑前后的整文件捕获来算增删行数。两条来源合并进同一份摘要,所以不在仓库里的文件也能出现在改动列表里。

DSH plugin 里,改动摘要里的 binary 和 oversized 标记分别代表什么?

DSH plugin 的改动文件里,binary 表示 git 判定为二进制或捕获侧含 NUL 字节,oversized 表示某一侧超过插件的 maxFileBytes。两者都只列出文件,不提供行数或对比内容。

DSH plugin 里,同一轮里多次宣告改动,客户端会显示几份摘要?

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

来源