Back to home

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-diff is the standalone, installable package name for the diff-viewer client plugin. Its canonical upstream home is the deepseek-harness monorepo at packages/client/ui-diff-viewer/ (there it is published as @deepseek-ai/dsh-client-ui-diff-viewer); this repository is the independently installable copy under the dsh-show-diff name.

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:

  • Settledblock.resultView when its card is 'diff' carries the applied contextual hunks the edit/write tools return (an edit's real before/after, a create's whole-file diff). This is authoritative and replaces the call-time view.
  • Runningblock.callView when its card is 'diff' carries the intended change derived from the arguments alone (an overwrite's oldText is null).
  • Malformed or absent — a card: 'diff' view whose diffs is 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.1 references 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-ai platform 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. The lib/client.js browser bundle is the part DSH loads, and it is committed to this repository (built from the upstream @deepseek-ai/dsh-client-ui-diff-viewer package 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 copy lib/ back with the id set to dsh-show-diff.
  • The node half is an empty apply so the plugin appears in the host composition; the browser half ships via exports["./client"], discovered through the dsh.client declaration in package.json.
  • It replaces, not augments, the shipped rows. Registering edit/write at priority -1 shadows the default file-mutation-toolview cells; 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.client package 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_path renders as an openable link (workspace-rooted paths display relative to the session cwd).
  • Collapse — the whole card collapses to its header with a toggle; DiffLines keeps its own height cap for very long diffs.
  • Inspect — the standard trajectory Inspect affordance 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/write replaces the shipped file-mutation-toolview for those names. The rows intentionally restore the shipped behavior when the bundle is removed; there is no coexistence mode.