kaiarvin
dsh-show-diff
Expanded color-coded diff tool cards for the edit/write tools — DeepSeek Harness client plugin with per-file line numbers
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 15, 2026
- Updated
- Aug 15, 2026
Introduction
dsh-show-diff
English | 中文
Installable plugin package.
dsh-show-diffis the standalone, installable package name for the diff-viewer client plugin. Its canonical upstream home is the deepseek-harness monorepo atpackages/client/ui-diff-viewer/(there it is published as@deepseek-ai/dsh-client-ui-diff-viewer); this repository is the independently installable copy under thedsh-show-diffname.
Expanded color-coded diff tool cards, browser half: registers the edit and write wire names in ui-tool's keyed tool.call.toolview slot. Each file mutation renders as an expanded diff card directly in the conversation flow — a header naming the mutation (Edit / Write) and its path, then the applied hunks through the package's line-aligned DiffLines surface, which draws the removed and added sides with the error/success colors, shows the old and new file line numbers per row (rebased onto each hunk's start line, so numbers are true file coordinates), collapses a long body at a height cap, and carries a copy affordance and a └ +A -R · N file(s) footer.
The old and new sides are aligned per line via a bounded LCS, so each row shows both its old-file and new-file line where the sides agree, the old line for a removal, and the new line for an insertion — the same reading a GitHub-style diff gives. The tools' result views carry each hunk's first file line (oldStart/newStart on the FileDiff contract); call-time views and older data without those fields fall back to numbering from line 1 within the hunk.
The default shipped file-mutation-toolview row also renders the same hunks, but inside a collapsed-by-default expanded body with an 8-line cap in the conversation flow. This package takes over the two keys so the change is visible at a glance: the card renders expanded, and the whole card can be collapsed with a header toggle. Registering a key the shipped composition already covers replaces that occupant — the rows register at priority -1, shadowing the shipped cells (same key at the same priority would throw); removing this bundle restores the shipped row.
Data source
The row derives its hunks and lifecycle only from the frozen call/result slice supplied by ui-tool, never from the filesystem:
- Settled —
block.resultViewwhen itscardis'diff'carries the applied contextual hunks theedit/writetools return (an edit's real before/after, a create's whole-file diff). This is authoritative and replaces the call-time view. - Running —
block.callViewwhen itscardis'diff'carries the intended change derived from the arguments alone (an overwrite'soldTextisnull). - Malformed or absent — a
card: 'diff'view whosediffsis not a well-formed hunk array routes the card to the empty state; an errored mutation keeps its model-facing error text on the output surface instead of a diff.
Replay stays stable: the hunks live on the persisted call/result views, so a window or session reload redraws the same change.
Install
This is an add-on client plugin for a DeepSeek Harness web deployment. It is not a standalone app: it extends an existing DSH web surface by taking over the edit/write tool cards, so you need a running DSH deployment first (it provides the platform modules the bundle imports, e.g. @deepseek-ai/dsh-client-ui-primitives).
Why the plugin cannot be installed standalone. The
@deepseek-ai/*packages are declared as peer dependencies — they are provided by your DSH deployment, not installed by this package. The early rc releases published to npm have incomplete dependency trees (e.g.dsh-client-runtime@0.0.1-rc.1references a package absent from the registry), so you must not try to install them yourself; install this plugin into a deployment that already satisfies those peers, and your package manager will never fetch the@deepseek-aiplatform from npm.
The package name is dsh-show-diff (no scope, so anyone can install it). Two installation routes:
Option A — install from this git repository (no npm publish needed)
Add the repository as a dependency of your DSH deployment, then add the plugin row. With pnpm:
# in your deployment's package.json, or via pnpm add:
pnpm add dsh-show-diff@git+https://github.com/kaiarvin/dsh-show-diff.git
Then add one row to the web surface's cordis.patch.yml (or any later patch layer):
- id: ui-diff-viewer
name: 'dsh-show-diff'
Option B — publish to npm, then install
# once, from this repository, with your npm credentials:
npm publish
# then, in any DSH deployment:
pnpm add dsh-show-diff
…and add the same cordis.patch.yml row as above.
Prerequisites and notes
- The built
lib/ships in the repository. Thelib/client.jsbrowser bundle is the part DSH loads, and it is committed to this repository (built from the upstream@deepseek-ai/dsh-client-ui-diff-viewerpackage in the deepseek-harness monorepo, with the standalone package id). A git install therefore works out of the box. To rebuild from source, run the build inside a deepseek-harness checkout:pnpm --filter @deepseek-ai/dsh-client-ui-diff-viewer run bundle, then copylib/back with the id set todsh-show-diff. - The node half is an empty
applyso the plugin appears in the host composition; the browser half ships viaexports["./client"], discovered through thedsh.clientdeclaration inpackage.json. - It replaces, not augments, the shipped rows. Registering
edit/writeat priority-1shadows the defaultfile-mutation-toolviewcells; removing the row (or the dependency) restores the shipped cards. - Runtime platform packages are peers.
@deepseek-ai/*are peer dependencies: your DSH deployment already provides them, so you do not install them yourself. - Restart the web process after adding the row so the new
dsh.clientpackage is scanned into the boot manifest.
Behavior
- State — running calls announce "Applying change"; failures show the first error line and the error state; interrupted calls use the warning state. Colour-only cues carry a visually hidden state label.
- Path — the mutation's
file_pathrenders as an openable link (workspace-rooted paths display relative to the sessioncwd). - Collapse — the whole card collapses to its header with a toggle;
DiffLineskeeps its own height cap for very long diffs. - Inspect — the standard trajectory
Inspectaffordance is offered when available.
Model Experience
This package is purely a client presentation surface: it registers no tools, emits no session events, and adds no tokens or model-visible context. The model-facing edit/write tools and their result text are unchanged; only how their calls render in the conversation flow differs.
Known Limitations and Deferred Work
- Result-only history pages use the generic row — keyed dispatch needs the paired call in the runtime window; pagination that leaves the call outside has no tool identity, and this presentation feature does not extend the history wire contract to recover it.
- Line numbers are hunk-relative when the data lacks file coordinates — call-time views and older persisted results carry no
oldStart/newStart, so those hunks number from line 1 within the hunk rather than the file; result views produced by current tools carry true file lines. - Takeover, not additive — occupying
edit/writereplaces the shippedfile-mutation-toolviewfor those names. The rows intentionally restore the shipped behavior when the bundle is removed; there is no coexistence mode.