Skip to content
hZsFNPublic

About

Repair tool for DeepSeek Harness (dsh): probes, AI diagnosis, transactional repair

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

Repository files navigation

dsh-fix — a repair tool for DeepSeek Harness

English · 简体中文

Diagnose and repair a local DeepSeek Harness (dsh) installation: probe → AI diagnosis → transactional repair.

Zero runtime dependencies (Node built-ins only, Node ≥ 22.19). That matters: it still runs when dsh itself is broken. That is the whole reason this is a standalone tool rather than a dsh plugin — a plugin goes down together with the thing it is supposed to fix.

machine probe  (deterministic, costs nothing)
      ↓
AI diagnosis   (DeepSeek official API, reads the report only)
      ↓
repair plan    (model may only pick from an action registry — it cannot make you run a command)
      ↓
transactional execution  (snapshot → journal → apply → generate a one-click rollback script)

Layout

~/.dsh/dsh-fix/
├── src/
│   ├── core/
│   │   ├── paths.mjs      path resolution (DSH_HOME / DSH_FIX_HOME overrides)
│   │   ├── util.mjs       file/process/string helpers, secret redaction
│   │   ├── config.mjs     config store + 3-tier API key resolution
│   │   ├── deepseek.mjs   DeepSeek official API client (models / chat / balance / streaming)
│   │   ├── probes.mjs     deterministic probe engine (the single source of truth)
│   │   ├── ai.mjs         AI diagnosis layer (prompt + output validation)
│   │   ├── journal.mjs    transaction journal + undo + rollback script generation
│   │   ├── repair.mjs     repair action registry + transactional execution engine
│   │   └── index.mjs      public entry point
│   ├── server.mjs         local web console (HTTP + JSON API + SSE)
│   └── cli.mjs            CLI entry point
├── ui/                    console front-end (plain HTML/CSS/JS, no build step)
├── assets/
│   ├── icon.svg           icon source (viewBox only — never add width/height)
│   └── dsh-fix.ico        generated multi-size icon (6 frames, PNG-compressed)
├── tools/
│   ├── make-icon.mjs      rebuild .ico from icon.svg
│   ├── check-ico.mjs      independently validate the .ico container
│   ├── make-shortcut.ps1  create desktop / start-menu shortcuts
│   └── publish.ps1        maintainer preflight + publish (secret scan before any push)
├── test/                  acceptance tests
└── config.json            tool config (generated at runtime, holds your API key — never share)

Runtime data: journals/, reports/, backups/, quarantine/. All of it is git-ignored.

Quick start

cd %USERPROFILE%\.dsh\dsh-fix

node src/cli.mjs status                     # show config and where the key comes from
node src/cli.mjs login --key sk-xxxxxxxx    # verify and store your official API key
node src/cli.mjs models                     # fetch the official model list
node src/cli.mjs probe                      # probe only (no AI, costs nothing)
node src/cli.mjs diagnose                   # probe + AI diagnosis
node src/cli.mjs ui                         # open the local console

On Windows you can also just double-click dsh-fix.cmd.

Desktop shortcut

pwsh -File tools\make-shortcut.ps1              # desktop (default name)
pwsh -File tools\make-shortcut.ps1 -StartMenu   # also add to the Start menu
pwsh -File tools\make-shortcut.ps1 -Force       # overwrite an existing one
pwsh -File tools\make-shortcut.ps1 -Name 'dsh-fix'

The script reads the shortcut back and verifies the target and icon. Launching it twice is safe: if a console of this tool already owns the port, it just opens the browser instead of starting a second instance.

To change the icon, edit assets/icon.svg (and remember: do not add width/height to the root element), then:

node tools/make-icon.mjs     # rebuild the .ico
node tools/check-ico.mjs     # validate the container

make-icon.mjs renders one 512px master image and downsamples it, then verifies the opaque-pixel coverage of every frame (expected 70–95%) and fails loudly otherwise. Reason: headless Chrome on Windows renders broken fragments for some window sizes — measured coverage drops to 45% / 14% / 0% at 256 / 192 / 128 — so without that check you silently ship a corrupt icon.

API key

Resolved in this order, first hit wins (the console always shows which one is in use):

  1. environment variable DEEPSEEK_API_KEY
  2. api.apiKey in ~/.dsh/dsh-fix/config.json
  3. refs.DEEPSEEK_API_KEY in ~/.dsh/.credentials.yaml

So an already-configured machine works out of the box. login --mirror also writes the key back to .credentials.yaml.

Keys are never echoed in clear text: the API only ever returns a mask (like sk-abc…wxyz), and logs, evidence and AI output all pass through redaction.

The model list comes from the official GET /models. If that call fails, the tool falls back to a built-in list and labels it source: fallback. /user/balance feeds the balance display so you are never surprised about spend.

Probes (deterministic)

All read-only. Nothing is modified, no AI is called.

Group What is checked
runtime Node version satisfies ^22.19.0 || >=24, dsh launcher, pnpm, git
home DSH home exists / is writable, profiles/, settings.yaml, .credentials.yaml
profile package.json parses, dsh.profile.bundles, YAML syntax of cordis.yml / cordis.patch.yml, pnpm-lock.yaml, MCP entries missing config
deps missing dependencies, full node_modules integrity scan (placeholder packages / dangling symlinks), link: / file: / git &path: deps, plugin-declared dsh engine compatibility
config settings.yaml parses, credential reference count, DeepSeek key visibility
service port listening, HTTP health (401 counts as healthy — the service is up)
logs error-signature lines in the last 7 days (module not found, syntax errors, port in use…)
disk free space
recovery available .bak-* backups, journal directory

Health score: 100 - failures×12 - warnings×3, floored at 0.

Design note: severity is graded

The same check distinguishes fatal from merely untidy. For the node_modules scan:

  • placeholder package (directory present, package.json absent) → fail: it breaks the plugin tree, the web app will not boot.
  • dangling symlink (left over from a directory that no longer exists) → warn: if nothing requires it, it is just residue.

Without that split the tool would recommend reinstalling an entire dependency tree over a harmless leftover.

Repair action registry

The AI may only pick actionIds from this list. It cannot supply a command to run. Anything it proposes that is not registered is demoted to a "manual step" with a warning and is never executed.

actionId Risk Effect
home.create-dirs low create missing standard directories
profile.create-cordis-patch low create a missing cordis.patch.yml (contents [])
logs.archive-old low archive logs older than 30 days (journaled per file, reversible per file)
backup.create low full ~/.dsh backup (node_modules excluded)
deps.prune-dangling-links low remove dangling symlinks (rollback recreates them)
profile.restore-yaml-backup medium restore broken YAML from the newest .bak-*
profile.restore-package-json medium restore package.json from the newest .bak-*
config.restore-settings-backup medium restore settings.yaml from the newest .bak-*
deps.install medium run pnpm install
deps.repair-broken medium quarantine placeholder packages, then reinstall
service.restart high generate a restart script (generated only by default, not run)
custom.script-N custom run your own script registered under repair.customScripts

Risk gating is enforced in code: medium needs allowMediumRisk, high needs allowHighRisk, both off by default. A gated action is shown explicitly as "needs authorization" in the preview rather than being silently skipped.

Transactions and rollback

  1. Original files are copied to backups/<journal-id>/ and journaled before anything is changed.
  2. Every step is appended to journals/<journal-id>/journal.json, so even a crashed repair is reversible afterwards.
  3. On completion a one-click rollback script is written to ~/.dsh/scripts/rollback-<task>-<timestamp>.ps1 (UTF-8 BOM + CRLF so Chinese renders correctly under Windows PowerShell 5.1), and it is validated with PowerShell's own parser before being handed over — a one-click restore that does not run is worse than none.
  4. The console's history tab can replay the rollback per journal, or regenerate the script.

Steps that cannot be undone automatically (like pnpm install) are listed explicitly as "needs manual handling" in both the journal and the script.

CLI

status                     config, key source, recent repair history
models                     fetch the official model list + balance
login --key sk-… [--mirror]
set --model/--base-url/--profile/--port/--allow-medium/--allow-high
probe [--verbose] [--json] [--out FILE]
diagnose [--question "…"] [--model ID] [--json]
actions                    list actions (risk, applicability, authorization)
repair --actions a,b [--yes]     dry-run by default; --yes actually applies
repair --ai [--yes]              apply the AI's plan directly
journals / undo <id> / rollback-script <id>
ui [--port 3099] [--no-open]
selftest                   core self-check

Local web console

node src/cli.mjs ui → http://127.0.0.1:3099/

Loopback only — this process can modify your dsh installation and should never be exposed. Four tabs:

  • Probe & diagnose — one-click probe (free), streaming AI diagnosis, root causes and plan, "carry into repair page" to pre-select actions.
  • Repair — action list with risk badges, authorization hints and preview commands. Preview is a dry-run; applying asks for confirmation.
  • History & rollback — repair history, step detail, rollback-script generation, one-click undo.
  • Connection & settings — verify/store the key, model and target profile, current state.

Tests

One command runs all three suites (recommended; leaves no trace in the real data directory):

node test/run-all.mjs          # --keep preserves the temp state dir for debugging

It spins up an isolated console of its own: DSH_HOME stays real (the probes must inspect the real machine) while DSH_FIX_HOME points at a temp directory (journals, reports, backups and quarantine all land there). The server is stopped and cleaned up afterwards.

Or run them individually (start a console yourself first):

node test/verify-core.mjs           # probe / gating / dry-run / transactions / rollback / AI validation
node src/cli.mjs ui --port 3099
node test/verify-ui.mjs             # HTTP API end-to-end (path traversal, unknown actions, risk gating)
node test/verify-ui-browser.mjs     # real browser via CDP, incl. rendering and runtime-error checks

⚠️ If you run an isolated console (i.e. you set DSH_FIX_HOME), pass the same DSH_FIX_HOME to verify-ui.mjs: it creates a journal of its own to exercise "generate rollback script / undo", and a mismatched state directory makes it fail with "journal not found". run-all.mjs already handles this.

verify-core.mjs builds a deliberately broken profile under testbed/ (bad YAML, missing deps, a placeholder package, a dangling symlink, a broken link: dependency) and asserts that the probes catch every one, that dry-run changes nothing, that a real repair is reversible, and that the generated .ps1 parses under PowerShell and actually restores the state.

150 assertions across the three suites; currently all green.

Security boundaries (stated explicitly)

  • The AI cannot execute commands. It can read the probe report, emit a structured diagnosis, and pick actionIds from the registry. Nothing else.
  • Dry-run by default. repair without --yes, or "Preview" in the console, touches nothing.
  • High-risk actions do not run by default. service.restart only generates a script; running it would kill the session you are currently in.
  • Keys are never echoed and never logged; evidence and AI text are redacted.
  • Loopback only (127.0.0.1).
  • deps.install / deps.repair-broken rewrite node_modules. pnpm's hard-linking will overwrite locally patched files, so re-run your own patch pipeline afterwards. The action description, the AI prompt and the costNote all say so.

Known trade-offs

  • Probes judge structural integrity, not behavioural correctness. A package whose files are all present but whose contents are wrong will not be caught; that needs log signatures plus AI reasoning.
  • YAML parsing reuses a js-yaml already present in the profile; if none is found it degrades to a built-in structural check (tab indentation, quote balance, bracket balance) and states which parser was used in the evidence.
  • Repair actions cover the environment/dependency layer. Bugs inside a plugin's own logic are out of scope for automatic repair.
  • The desktop-shortcut and icon tooling is Windows-specific; the core CLI and probes are portable.

License

MIT

About

Repair tool for DeepSeek Harness (dsh): probes, AI diagnosis, transactional repair

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages