Skip to content

feat(installer): add DeepSeek Harness (dsh) target - #1591

Open
hfldqwe wants to merge 3 commits into
colbymchenry:mainfrom
hfldqwe:feat/dsh-target
Open

feat(installer): add DeepSeek Harness (dsh) target#1591
hfldqwe wants to merge 3 commits into
colbymchenry:mainfrom
hfldqwe:feat/dsh-target

Conversation

@hfldqwe

@hfldqwe hfldqwe commented Aug 22, 2026

Copy link
Copy Markdown

What

Adds DeepSeek Harness (dsh) as a supported agent for codegraph install / codegraph uninstall, alongside the existing targets.

dsh does not use an mcpServers JSON shape: MCP servers are Cordis plugin rows (@deepseek-ai/dsh-mcp-client), declared in layered YAML patch files. This target writes one root - insert: patch entry into $DSH_HOME/cordis.patch.yml (default ~/.dsh, DSH_HOME env override) — the home-level layer that applies to every dsh profile at once and is hot-reloaded by a running session:

- insert:
    - id: mcp-codegraph
      name: '@deepseek-ai/dsh-mcp-client'
      config:
        serverName: codegraph
        transport: stdio
        command: codegraph
        args:
          - serve
          - --mcp
        failOnStartupError: false

Global-only (like Codex and Hermes); no instructions file, per the #529 policy. Because dsh passes no workspace root to MCP servers, the README/site entries carry a note pointing at projectPath.

Why this PR (relationship to #1572)

#1572 covers the same feature with the right architecture — this PR is an independent implementation that also fixes three defects found in its approach, with the same overall shape and file coverage otherwise:

  1. Indent matching. feat(installer): DeepSeek Harness (dsh) as a supported agent #1572 appends the entry at a fixed indent into the last - insert: block. dsh parses cordis.patch.yml with js-yaml, which rejects a block sequence with mixed item indents — so a user file using 2-space style becomes unbootable (loadOptionalPatches fails loud at boot). Same bug class as the Hermes PyYAML-style fix (Bug: codegraph install --target hermes corrupts config.yaml — drops hermes-cli and breaks nested YAML indentation #456). This target detects the block''s item indent and appends/canonicalizes at that indent (regression test included).
  2. [] handling. feat(installer): DeepSeek Harness (dsh) as a supported agent #1572 appends after a lone [] line, producing invalid YAML; [] is dsh''s own documented empty state. This target replaces the token in place, preserving surrounding comments, and repairs comments-only files (which also fail to boot).
  3. Override-patch safety. Entry detection here requires both the mcp-codegraph id and the plugin name, so a user''s id-targeted override patch row is never treated as ours or clobbered.

Also included: install migrates a pre-existing per-profile codegraph entry up to the home layer (a duplicate serverName across live plugin instances fails the later instance at load) and uninstall sweeps profiles for symmetry; hand-written flow-style entries are detected as configured but left untouched (Kept + a pointer at codegraph install --print-config dsh) instead of being duplicated.

Implementation

  • New src/installer/targets/dsh.ts — hand-rolled CRLF-safe line editor in the hermes.ts house style (no new dependencies); full uninstall state matrix (siblings survive, comments-only remainder restored to [], installer-created file deleted when only its stamped header remains).
  • Wiring: TargetId union, registry (appended last), install/uninstall command descriptions, installer header comment, ~/.dsh uninstall location hint.
  • Docs: CHANGELOG [Unreleased] entry; README agent lists (incl. a projectPath note and the live-reload restart caveat); the six docs-site agent lists plus a manual-setup snippet in reference/integrations.md. Site-list scope is deliberately DSH-only (the pre-existing Copilot lag there is left as-is).

Testing

  • 22 dedicated dsh tests in __tests__/installer-targets.test.ts (indent-matching regression, [] round-trip, comments-only repair, sibling + override-patch preservation, per-profile migration + uninstall symmetry, flow-style kept paths, DSH_HOME precedence, CRLF) on top of the parameterized contract suite''s automatic coverage: 245 passed / 3 platform skips / 0 failed; legacy installer.test.ts 3/3.
  • tsc and npm run build clean; full suite shows no new failures vs main (pre-existing Windows/EPERM flakes documented in CLAUDE.md).
  • End-to-end against a real dsh installation: the written file composes into dsh --profile web --dump-config with exactly one canonical mcp-codegraph row (the profile+home duplicate-serverName collision was reproduced pre-fix and verified swept post-install); the 2-space-style file parses with dsh''s own js-yaml dialect and boots; install/uninstall round-trips byte-cleanly on adversarial files (comments + sibling patches + id-override rows + CRLF).

Adds DeepSeek Harness (dsh) to `codegraph install` / `codegraph
uninstall` as a supported agent, alongside the existing targets.

dsh does not use an `mcpServers` JSON shape: MCP servers are Cordis
plugin rows (`@deepseek-ai/dsh-mcp-client`), declared in layered YAML
patch files. The target writes one root `- insert:` patch entry into
`$DSH_HOME/cordis.patch.yml` (default `~/.dsh`, `DSH_HOME` env
override) — the home-level layer that applies to every dsh profile at
once and is hot-reloaded by a running session. Global-only, like
Codex and Hermes; no instructions file (the MCP initialize
instructions stay the single source of truth, issue colbymchenry#529).

Editor details (hand-rolled line editor, no new dependencies):

- Appending into an existing `- insert:` block MATCHES that block's
  item indent, and a differing pre-existing codegraph entry is
  canonicalized in place at its own indent. js-yaml (which dsh uses to
  parse the file) rejects block sequences with mixed item indents, so
  a naive fixed-indent append can produce a file that aborts the dsh
  boot — the same bug class as the Hermes PyYAML-style fix (colbymchenry#456).
- A lone `[]` line (the documented empty state) is REPLACED with the
  entry, not appended after; a comments-only file (which also fails to
  boot) is repaired; comments and sibling patch entries are preserved
  through every operation.
- Entry detection requires both the `mcp-codegraph` id and the plugin
  name, so a user's id-targeted override patch row is never touched.
- Uninstall reverses cleanly: siblings survive, a user comments-only
  remainder is restored to `[]`, and a file this installer created is
  deleted when only its stamped header remains.
- Install migrates a pre-existing per-profile codegraph entry up to
  the home layer (a duplicate `serverName` across live plugin
  instances fails the later instance at load); uninstall sweeps every
  profile patch for symmetry.
- Hand-written flow-style codegraph entries are detected as
  configured but left untouched (`Kept` + a pointer at
  `codegraph install --print-config dsh`), rather than duplicated.

Wiring: `TargetId` union, registry (appended last), install/uninstall
command descriptions, installer header comment, and the `~/.dsh`
uninstall location hint.

Tests: 22 dedicated dsh tests in `__tests__/installer-targets.test.ts`
(indent-matching regression, `[]` round-trip, comments-only repair,
sibling + override-patch preservation, per-profile migration and
uninstall symmetry, flow-style kept paths, `DSH_HOME` precedence,
CRLF) plus the parameterized contract suite's automatic coverage.
Docs: CHANGELOG `[Unreleased]` entry, README agent lists with a
`projectPath` note (dsh passes no workspace root to MCP servers), and
the six docs-site agent lists including a manual-setup snippet.
…tups

Borrowed from colbymchenry#1572 (verified against the dsh-mcp-client schema: `cwd`
is a supported stdio field): the README dsh bullet and the dsh.ts
module doc now explain that the agent passes `projectPath` (per the
server's no-root-index guidance) OR the user can pin `cwd` / `--path`
on the entry for a single-project setup. Also rebased onto main
(includes colbymchenry#1551 project-local Codex, colbymchenry#1463 deprioritize, and the
merged contributor batch).
@hfldqwe

hfldqwe commented Aug 23, 2026

Copy link
Copy Markdown
Author

Quick status update for review: this PR is now rebased onto the latest main (includes #1551 project-local Codex) and merges cleanly — installer-targets.test.ts 252 passed / 3 platform skips, full suite shows no new failures vs main, and the adversarial E2E suite (144 checks incl. real dsh --profile web --dump-config composition, the 2-space mixed-indent regression, and install/uninstall round-trips on adversarial files) is green.

One small improvement was borrowed from #1572 with credit in 6e6b805: the README/module docs now also mention cwd / --path pinning as the single-project alternative to projectPath.

Happy to coordinate with the #1572 author or adjust in whatever direction the maintainer prefers — the main deltas beyond #1572 are the three verified fixes listed in the description (indent-matched append — the fixed-indent append produces a mixed-indent file that fails loud at dsh boot with js-yaml, repro provided; [] replaced in place instead of appended after; user override-patch rows never touched), plus per-profile serverName collision sweep and conservative kept handling for hand-written flow-style entries.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant