DSH plugin deliverables: present, PresentedFile and diffs
A DSH plugin's "deliverables" are really two independent channels: files the model explicitly declares through present, and files actually changed during the turn. The first comes from a tool call; the second comes from comparing git worktree snapshots at turn start and turn end, with paths git cannot cover filled in by whole-file captures around each file-tool edit. Both are announced by log-only events, but the crucial difference is that the summary itself is not in the log — the Host serves it while the session is alive. That explains a familiar surprise: after a Host restart, earlier turns in a reopened conversation have no change cards.
DSH plugin deliverable channels: declaration and change
Bottom line: present covers "what I delivered," workspace/changes covers "what this turn modified," and neither substitutes for the other.
| Channel | Trigger | Recorded as | Content |
|---|---|---|---|
| present declaration | Model calls the present tool | Log-only deliverables/presented | Paths and descriptions |
| Turn changes | Top-level turn stops | Log-only workspace/changes | Event carries only the turn; Host serves the summary |
- Both are read-only: clients read and render them at turn end; the server never uses them to alter model context.
- They do not overlap: a declared but unmodified file appears only in presented; a modified but undeclared file appears only in the change summary.
- Do not treat the event as data:
workspace/changescarries onlyturn; ask the Host for the summary.
DSH plugin PresentedFile: present lands in the event
Bottom line: each successful present appends one event with turn, call id and files; content stays at the source path.
interface PresentedFile {
path: string // absolute or relative to the session cwd
description?: string
}
- Write timing: the event is appended only when the present call's final result succeeds.
- Content is not moved: the declaration registers a path; the file stays where it is.
- One call, one event:
{ turn, callId, files }, with callId identifying the model's tool call. - Good fits: reports, screenshots, exported tables — "please look at this artifact."
- Bad fits: use the change summary for "which files I modified," not present.
DSH plugin change sources: git snapshots plus whole-file captures
Bottom line: with git, compare turn-start and turn-end worktrees; without it, use before/after file-tool captures, then merge.
- Git path: compare turn-start and turn-end worktree snapshots for changed files and line counts.
- Non-git path: whole-file captures before and after each file-tool edit fill the gap.
- Display label: relative inside the working directory,
../above it,~under home, otherwise absolute, always slash-separated. - Special markers:
binarywhen git reports binary or a capture side holds a NUL byte;oversizedwhen one side exceedsmaxFileBytes. - Caps:
filessorts by display and caps atmaxFiles, whiletotal,addedanddeletedstill count every file. - Snapshot ids:
snapshot.beforeandsnapshot.afterare git tree ids, absent when no snapshot was taken.
DSH plugin summary access: summary and diff
Bottom line: ask the Host by event seq; diffs are computed per file index and disappear when the session is released.
const summary = ctx.workspaceChanges.summary(sessionId, seq)
const diff = await ctx.workspaceChanges.diff(sessionId, seq, index, signal)
- Summary conditions: the session is alive and this Host recorded the event; otherwise
undefined. - Diff inputs: event seq plus the file's index in
files, returning text, binary or oversized. - Text shape:
hunksin file order, empty when both sides match;coarsebecomes true when comparison exceeds the timeout and every line shows as replaced. - Binary and oversized: no line content, only
pathanddisplay. - Failure semantics: snapshot read failures on a live session throw rather than returning an empty diff.
DSH plugin event boundaries: not in model requests, summaries are not durable
Bottom line: neither event enters model requests, and summary availability depends on the Host — a design boundary, not a bug.
- Invisible to the model:
deliverables/presentedandworkspace/changesnever enter model requests. - Rendered at turn end: the Web deliverables plugin renders both channels together.
- Restart boundary: after a Host restart, earlier turns lose their change cards because summaries were never persisted.
- Same-turn supersession: later events replace earlier ones and clients keep the latest.
- Need durability? Copy the summary into your own storage, such as a StorageBackend.
DSH plugin deliverable troubleshooting
Bottom line: separate not recorded, recorded but empty, and gone after restart.
- Declared but not shown — check that present's final result succeeded; failures append nothing.
- Files changed but the list is empty — confirm changes happened in the top-level turn and check
maxFiles. - Line counts missing — the file was marked binary or oversized.
- Summary is undefined — the session was released or this Host never recorded the event.
- Everything shows as replaced —
coarseis true because comparison exceededdiffTimeoutMs. - Repair status, stated honestly: the two channels, field definitions, summary serving and restart boundary follow the official Deliverables page and the two package READMEs; configuration keys are defined by those packages.
Sources: Deliverables, tool-present README, workspace-changes README.
FAQ
No: DSH plugin deliverables have two independent channels. present records files the model deliberately delivers, while the change summary lists files actually modified in the turn using git snapshots and file-tool captures; neither replaces the other.
The DSH plugin workspace/changes event only announces that a turn had changes; the summary itself is served by a Host service while the session is alive. After a Host restart, previously reopened conversations have no change card for earlier turns.
For paths git does not cover, the DSH plugin compares whole-file captures taken before and after each file-tool edit to derive added and deleted lines. Both sources merge into one summary, so files outside repositories still appear.
In DSH plugin changed files, binary means git reported it as binary or a captured side holds a NUL byte, while oversized means one side exceeded the plugin's maxFileBytes. Both list the file without line counts or diff content.
Later DSH plugin events in the same turn supersede earlier ones and the client keeps only the latest. Do not infer how many edits happened from event count; the summary's total is the complete file count.
Related Terms
- PresentedFile
- PresentedFile is a file the model declares as delivered through the present tool, with a path and optional description while the content stays at its source path. It is recorded in a log-only session event.— https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/deliverables.zh.md
- WorkspaceChangedFile
- WorkspaceChangedFile describes one file changed during a turn, with a relative path, display label, added and deleted line counts and optional binary or oversized markers. Counts come from git or whole-file captures around file-tool edits.— https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/deliverables.zh.md
- WorkspaceChangesSummary
- WorkspaceChangesSummary is the change rollup for one top-level turn: turn number, cwd, files in display order, complete counts and totals, plus optional git tree snapshot ids. It is not stored in the event log and is served by the Host.— https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/deliverables.zh.md
- WorkspaceDiffHunk
- WorkspaceDiffHunk is one unified diff hunk with three context lines, recording old and new start lines and counts while every body line keeps its +, - or space prefix. Several hunks form one file's text comparison.— https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/deliverables.zh.md
Sources
- DeepSeek Harness docs — Deliverables (PresentedFile, WorkspaceChangesSummary, serving summaries and diffs)· deepseek-ai (GitHub)
- tool-present package README (present tool behavior and configuration)· deepseek-ai (GitHub)
- workspace-changes package README (snapshot mechanism and limits)· deepseek-ai (GitHub)