dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
The rich edit tool for DeepSeek Harness (replace / patch / apply_patch / hashline modes) with embedded format-on-write and diagnostics — plus dsh-hashline, the pure line-anchored patch engine.
[!NOTE]
📦 This plugin lives in the dsh-plugins monorepo — file issues & pull requests there.
npm:@hy-sde-org/dsh-hashline·@hy-sde-org/dsh-tool-edit
edit tool for DeepSeek HarnessTwo standalone packages, installable as one plugin for the DeepSeek Harness CLI:
package · role · installed by users? @hy-sde-org/dsh-hashline · pure line-anchored edit-patch engine (library) · no — transitive @hy-sde-org/dsh-tool-edit · the plugin: edit tool (replace / patch / apply_patch / hashline) + embedded format-on-write & diagnostics · yes
The edit tool is a full parity port of oh-my-pi's coding-agent edit tool onto the harness tool/filesystem contract (ctx.tools, ctx.fs, ctx.systemPrompt). It reads through the filesystem before every edit — its own authoritative read records fs/observed, so a deployment's observation policy is satisfied in a single call the way omp's ToolSession was (no separate model-facing read required, and the observed-version CAS still rejects a concurrent mutation) — and it writes through the fs/edit-intent waterfall. The hashline snapshot store is shared per agent session through @hy-sde-org/dsh-hashline's getSessionSnapshotStore, so a [path#tag] header that a read/search tool minted validates against the exact content (and lines) the model saw: first-try tags, no re-read cycle. It also bundles its own LSP client, so formatOnWrite and diagnosticsOnEdit work on stock DeepSeek Harness deployments with zero upstream changes (the language server runs via npx typescript-language-server and degrades to edit-only when unavailable).
For coding agents, much of the leverage is in the harness, not the model — the "harness problem" [Stencil So][stencil] frames well: the tool surface (how a model reads, edits, and is shown errors) often bounds reliability more than the model does. This plugin is harness work: a better edit tool with a built-in language server, shipped as an installable plugin. The [benchmark section][benchmark] records the A/B run that measures it against the harness's built-in str_replace_editor, so the "it's better" claim is evidenced, not asserted.
[stencil]: https://stencil.so/blog/the-harness-problem [benchmark]: benchmark/README.md
engines floor) with npm and pnpm on PATH;dsh CLI — the peer baselineis @deepseek-ai/cordis ~4.0.4 and @deepseek-ai/dsh-* ^0.2.0-rc.2 (the minimal-patch posture below targets official harness releases rc.8 and later);
typescript-language-server reachable via npx for format-on-write anddiagnostics — the tool degrades to edit-only when unavailable.
pnpm install --global @deepseek-ai/dshBoth packages are published on the npm registry under the hy-sde-org organization (@hy-sde-org/dsh-hashline and @hy-sde-org/dsh-tool-edit, version 0.2.0-rc.2). Install the plugin straight from npm — the registry resolves the hashline library dependency and the DeepSeek Harness peer packages automatically, no tarballs, no ordering:
# one command; @hy-sde-org/dsh-hashline comes in as a transitive dependency
dsh plugin --profile web add @hy-sde-org/dsh-tool-editOn official harness releases (rc.8 and later) the bundle's patch seams are deliberately minimal (see Replacing the built-in editor): dsh plugin add reconciles the profile, disables the shipped str_replace_editor tool, and the rich editor is then mounted by adding the provided agent preset row. Installing the bundle alone never breaks boot and never claims the edit name on the host plane.
You can also just depend on the packages from your own tooling as normal npm dependencies:
npm install @hy-sde-org/dsh-tool-edit # or pnpm add / yarn add
npm install @hy-sde-org/dsh-hashline # the engine, if you need it directlyRegistry notes.latestis0.2.0-rc.2. That bundle uses the
minimal-patch posture that boots on official
harness releases; the earlier0.1.xreleases ofdsh-tool-editwere
published before the rc.7 bundle posture (they mounted a self-contained fs
realm that requires the enableEdit harness feature and fails boot on stockrc.7/rc.8) — do not install them on an official harness.
Before the registry publish (or when hacking on the repo itself), install from the built tarballs — and pin the unpublished dependency so pnpm add doesn't query the registry for @hy-sde-org/dsh-hashline:
git clone git@github.com:hy-sde/dsh-plugins.git
cd dsh-plugins
pnpm install
pnpm --filter @hy-sde-org/dsh-hashline build
HASHLINE_TGZ="$(cd dsh-tool-edit/packages/hashline && pnpm pack --pack-destination /tmp | tail -n 1)"
dsh plugin --profile web add "$HASHLINE_TGZ"
# Pin hashline locally so the tool-edit tarball's dependency resolves offline.
printf 'overrides:\n "@hy-sde-org/dsh-hashline": "file:%s/packages/hashline"\n' "$PWD" >> "$DSH_HOME/profiles/web/pnpm-workspace.yaml"
TOOLEDIT_TGZ="$(cd dsh-tool-edit/packages/tool-edit && pnpm pack --pack-destination /tmp | tail -n 1)"
dsh plugin --profile web add "$TOOLEDIT_TGZ"(The overrides entry is a pre-publication shim; delete it once you're on the released registry package.)
Install order note: don't try to satisfy the dependency by installing the
hashline tarball "first" — pnpm re-resolves the full graph on every addand will 404 on an unpublished @hy-sde-org/dsh-hashline unless the overrideabove pins it.
dsh web --dump-config # the tool-str-replace-editor row is patched to disabled: truedsh plugin --profile web remove @hy-sde-org/dsh-tool-edit
dsh plugin --profile web remove @hy-sde-org/dsh-hashline
# remove the preset directory you copied from examples/agent-preset/ as wellThe official harness ships TWO editing surfaces host-wide: the tool-fs read/write/edit suite and a dedicated Anthropic-style str_replace_editor tool. On stock releases this plugin replaces them like this:
cordis.patch.yml patches the shipped tool-str-replace-editor row to disabled: true (re-enable later with disabled: null).
harness scoped-tools semantics let a tool registered in the agent's own scope layer shadow a global tool of the same name. Mounting the plugin's tool-edit row in a user agent preset makes edit resolve to the rich editor, while read/write keep resolving from the deployment's host tool-fs. No host-plane bundle row can do this: the official tool-fs has no way to disable its own edit (the enableEdit: false key exists only in the hy-sde fork), so a second edit-owner on the host plane fails boot with "prompt section tool:edit is already registered".
The ready-to-copy preset ships in the package under examples/agent-preset/ (agent.cordis.yml + preset.yml). Install:
# from the installed package or this repo:
mkdir -p ~/.dsh/.agent-presets/my-edit
cp packages/tool-edit/examples/agent-preset/agent.cordis.yml \
packages/tool-edit/examples/agent-preset/preset.yml \
~/.dsh/.agent-presets/my-edit/
# then select "Edit Mode (rich)" in the Web UI preset picker (or `dsh agent`)The example preset mounts the rich editor beside the LSP seam in an entry-local realm (isolate: { lsp: true }) so format-on-write and diagnostics-on-edit work with zero upstream changes, and explicitly omits tool-fs — keeping the per-session tool-fs row would register the stock edit in the same scope and fail the preset boot. Copy the other rows you normally use (bash, todo, ask-user, skills, …) from your current preset next to these; only the filesystem-editing rows are special. read/write always keep coming from the deployment's host tool-fs.
On official releases the plugin's cordis.patch.yml is intentionally *not* self-contained: a host-plane fs realm cannot own the edit name because the official tool-fs always registers edit (no enableEdit switch) — every variant collides at boot. What the patch does instead:
tool-str-replace-editor → disabled: true — retires the standalonestr_replace_editor tool the harness ships host-wide (matches the hy-sde fork, which deleted the package outright).
section above, where scoped shadowing makes it THE edit tool.
The hy-sde fork already integrates the rich editor directly in its shipped presets (code-edit, minimal); there you keep mounting @hy-sde-org/dsh-tool-edit in a preset beside tool-fs with enableEdit: false (fork-only key), and the bundle patch above is a harmless no-op (the str_replace_editor row does not exist there — the loader warns and continues).
Configure the tool by patching the tool-edit row in your preset by id:
- id: tool-edit
config:
mode: hashline # 'auto' | 'hashline' | 'replace' | 'patch' | 'apply_patch'
formatOnWrite: true
diagnosticsOnEdit: true
lspCommand: npx --yes typescript-language-server --stdio
typescriptNative: {} # opt-in: tsc --lsp --stdio for TS7 workspacesThe single edit tool dispatches on argument shape (or is pinned to one mode via config.mode; the default is hashline for input payloads, while replace/patch argument shapes keep routing automatically):
mode · argument shape · notes replace · path + old_string + new_string (replace_all) · fuzzy whitespace matching by default patch · path + edits[] · JSON edit entries apply_patch · input · Codex/Aider-style patch envelope hashline · input · line-anchored patch language: tags the model saw (@file) + @@ blocks referencing line numbers and hashes
typescript-language-server on first edit thatwrites through LSP; the server process is shared for the plugin lifetime and torn down on unmount.
install has no lib/tsserver.js (TS7+) spawns the native tsc --lsp --stdio from the workspace's own launcher (or the tsc resolved on PATH) instead of the wrapper, which cannot drive TS7; classic and undetectable workspaces keep lspCommand unchanged (upstream oh-my-pi 530664c8f5).
formatOnWrite, edited files are formatted viatextDocument/formatting before the write lands.
diagnosticsOnEdit, textDocument/publishDiagnostics are attached tothe edit result as an N error(s), M warning(s) summary with line:col [severity] [source] message lines.
silently. Never blocks an edit.
pnpm install
pnpm -r check # strict typecheck of both packages
pnpm -r test # hashline 246 tests + tool-edit 23 tests (incl. embedded LSP client)
pnpm -r build # tsc -> dist
bash scripts/release-public.sh --check # pre-publish validation
bash scripts/release-public.sh --publish # publish hashline then tool-editpackages/hashline/ @hy-sde-org/dsh-hashline — the engine (no runtime deps)
packages/tool-edit/ @hy-sde-org/dsh-tool-edit — the plugin (embedds the LSP client)
cordis.patch.yml the installable harness bundle
src/lsp/ embedded client: stdio framing, LSP client, provider,
writethrough (port of oh-my-pi's lsp writethrough)This package is licensed MIT — the same license as its upstream oh-my-pi (https://github.com/can1357/oh-my-pi). The hashline patch engine and the rich edit tool are a parity port of oh-my-pi's coding-agent edit tooling (MIT License, © Mario Zechner 2025, © Can Bölük 2025-2026); the upstream copyright holders are recorded in LICENSE next to this package's own notice, and the upstream notice text is reproduced in full in THIRD-PARTY-NOTICES.md. The TypeScript 7 native-launcher behavior tracks upstream oh-my-pi 530664c8f5 (see *LSP behavior on stock DSH* above).