deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
PROJECT README
Session-scoped diff decorations for the DSH Web right sidebar.
When you open a file that the current conversation changed, the sidebar renders it with git-style added/removed line highlighting plus syntax colouring, and a companion page lists every file this conversation touched.

write / edit tool rows already open the changed file in the right
sidebar. This plugin's tab type claims exactly those addresses (extension priority, and only
when the session really has changes for that path), so the same click now opens a view with:+ / - gutter markers,git diff,+added −removed, a "changes only / whole file" toggle, a changes-only view
that collapses long unchanged runs, and a re-read button.+/− counts and the containing directory; clicking an entry opens the decorated view.
Reachable from the file view's header button and from the right sidebar's guide page.Files the conversation did not touch keep the shipped text viewer — canOpen only vetoes
what it actually decorates, so images, PDFs, markdown and every other document renderer behave
exactly as before.
dsh plugin --profile web add github:2002XiaoYu/dsh-session-diff # or file:/path/to.tgz
# restart `dsh web` (dsh.profile.bundles is read once at boot)
# hard-refresh the browser (Cmd+Shift+R)
There is no npm release yet, so install from the repository: lib/ is committed next to src/,
which means a source install runs no build step. The same prebuilt artifact is attached to the
release, if you would rather not clone:
dsh plugin --profile web add https://github.com/2002XiaoYu/dsh-session-diff/releases/download/v0.1.0/dsh-session-diff-0.1.0.tgz
Once the package is published to npm, dsh plugin --profile web add dsh-session-diff works in the
same place.
dsh plugin adds the package to the profile and, because the package declares
dsh.bundle.patch, registers it in dsh.profile.bundles as a profile layer. Uninstall is the
same one command, with no configuration editing:
dsh plugin --profile web remove dsh-session-diff
There is no GUI entry point for installing plugins — the Settings → Plugins page lists and removes installed plugins, it does not add new ones.
npm run build # src/*.js -> lib/client.js (node, cross-platform)
bash install.sh # copy to ~/.dsh/plugins, symlink, add one patch-layer row
This path uses the profile's cordis.patch.yml instead of the bundle list, so patchReload: live
applies it without restarting dsh web — handy while iterating. Two rules come with it:
dsh.profile.bundles, the manual
patch row would insert the same loader row twice; install.sh refuses to run in that case.cordis.patch.yml must always be a top-level YAML array. When removing the row, leave the
file as []. A comments-only file parses to null and dsh web refuses to boot with
"must be a top-level YAML array of loader patches".Verify a profile is clean with:
dsh --profile web --dump-config | grep -c dsh-session-diff # 0 for an uninstalled profile
0.1.5-rc.1 (React 18 client runtime). The browser half only ever requires
platform seed modules — react, optionally @deepseek-ai/dsh-client-ui-primitives — and reads
everything else from the cordis context, so it does not need React or a UI kit of its own.apply; the plugin never spawns a shell,
never runs git, and never touches the filesystem directly. File contents are read through
DSH's own workspaceFiles remote, and the diffs come from the conversation's tool results.dsh web; after that, client-side changes only need a
browser refresh.write / edit results in the session you are
looking at. Changes made by another conversation, by hand, or before this conversation are not
shown — use git for that.write / edit results carry meta.diffs, an array of FileDiff = {path, oldText, newText}.
Each entry is one applied hunk with three lines of context on both sides and no line numbers
(dsh-tool-fs builds them with structuredPatch(..., {context: 3}); oldText is null only when
a hunk has no old lines at all). A whole-file, git-style decoration therefore cannot be read off
the hunks directly, so:
newText with its oldText, which reconstructs the pre-conversation text (occurrence
choice is hint-based, so repeated snippets resolve in place);+/− counts derived.npm install # devDependencies: jsdiff (real hunk fixtures), react + react-dom (SSR harness)
npm run build # node scripts/build.mjs -> lib/client.js (+ contract check)
npm test # diff engine, tokenizer, addresses, bundle load, registrations, SSR bodies
Both harnesses take an escape hatch so they also run without node_modules:
DSH_INSTALL=<a dsh install> supplies jsdiff from a DSH installation, and
REACT_DIR=<dir containing react and react-dom> supplies the renderer.
scripts/build.mjs is deliberately not a bundler. A DSH client bundle is a single lazy-CJS file:
executing it only registers window.__ModuleLoader__.load({id, factory}), and the factory body may
require nothing but the nine platform seed words. This plugin needs nothing beyond React and the
cordis context, so the bundle is the ordered concatenation of src/*.js inside that wrapper.
Publishing:
npm login
npm publish # unscoped name — no --access flag needed
The package name is unscoped (dsh-session-diff), so no npm scope or organisation has to be owned
first. A scoped name would have to resolve to a scope the publisher controls, and npm publish
fails with a 403 otherwise; the GitHub owner and the npm account do not have to match either —
this repository lives at 2002XiaoYu/dsh-session-diff. Renaming is safe: scripts/build.mjs
reads the name from package.json, injects it as the bundle's loader id, and fails the build if
cordis.patch.yml still registers the old name.
prepack rebuilds lib/client.js from src/ so the published artifact can never drift from the
sources. There is deliberately no prepare: npm and pnpm 10+ block lifecycle scripts for
installed dependencies, so a build-on-install would be silently skipped on a consumer's machine.
Consumers therefore never run a build — which also means a git-based install needs lib/
committed, since nothing rebuilds it there. The registry path and dsh plugin add <file.tgz>
are both self-contained.
src/00-head.js loader wrapper + React requires
src/10-util.js addresses, paths, copy, styles
src/20-tokenizer.js dependency-free syntax scanner (maps to --shiki-token-* vars)
src/30-diff.js hunk narrowing, baseline reconstruction, Myers line diff, row model
src/40-reader.js whole-file read through the workspaceFiles Remote (paged)
src/50-store.js conversation/session binding, per-file hunk aggregation, external store
src/60-ui-file.js decorated file body + tab title
src/70-ui-changes.js session changes page + tab title
src/80-apply.js tab-type and slot registrations
src/99-tail.js module.exports
scripts/build.mjs the whole build
test/ logic harness + bundle/registration/SSR harness CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。