dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
VS Code sidebar for DeepSeek Harness: native session tree, file and diff navigation, drag-to-reference, clipboard and theme bridges.
Embed the DeepSeek Harness (DSH) web agent in a VS Code
sidebar webview, pinned to the current workspace folder. It drives the open-source dsh CLI you install
yourself.
0.2.0-rc.1 or newer (tested with 0.2.0-rc.1), Node.js 22+ on the
host's PATH. Those CLI versions are documentation, not a gate: the extension launches the configured
command directly and reports what it does.dsh backend on the machine that hosts the
folder. Every window or Remote-SSH connection to that folder attaches to the same backend.The extension starts a DSH web runtime (dsh web) with the first VS Code workspace folder as its working
directory, proxies the authenticated page into a sidebar webview, and bridges the two sides: the page's own
sidebar is replaced by the VS Code folder, and file/diff navigation, reference chips, the sessions tree and
the theme all live in VS Code natively. The runtime belongs to the folder, not to the window: a detached
workspace keeper owns it, and every window or Remote-SSH connection to that folder attaches to the same one.
read / write tool paths in the conversation open the file in
VS Code; edit tool paths open a tool-change diff (old_string → new_string, independent of git).
The closing turn's produced-file chips, its file mentions in the prose (delivered files included), and
the delivery cards open in the editor too, and the card's chevron offers Open in Editor, Open to the
Side and Reveal in Explorer — the host's desktop application is never the target, which is what makes
them usable over Remote-SSH.@path#Lx-Ly reference chip. When the dragged file is the active editor with a non-empty
selection, the chip references that exact range; otherwise it references the whole file. Every drop reports
what happened: chip inserted, dragged text placed in the composer, or one warning naming why it failed.ctrl+alt+d / cmd+alt+d references the current selection, or the
enclosing code block at the cursor when nothing is selected.navigator.clipboard, which the browser refuses.workbench.colorScheme, live, without touching the shared
DSH settings document.0600) share record. The proxy injects it
upstream, so the cookie never reaches the client browser.VS Code 1.96+
Node.js 22+ on the PATH of the machine that hosts the folder (Remote-SSH and containers are
supported): dsh is a Node CLI and runs under whichever node it finds there, not VS Code's bundled Node.
DeepSeek Harness on the extension host's PATH:
npm install -g @deepseek-ai/dsh
The extension's workspace keeper launches the configured command directly — there is no pre-flight version
check. A CLI that cannot serve dsh web fails with its own message on the Agent view's startup page and in
the DSH Sidebar output channel. See Compatibility.
No Marketplace listing yet — install the VSIX from Releases:
code --install-extension dsh-sidebar-<version>.vsix
For Remote-SSH, install on the server (the extension runs where the folder is):
~/.vscode-server/bin/<commit>/bin/code-server \
--install-extension dsh-sidebar-<version>.vsix \
--force --extensions-dir "$HOME/.vscode-server/extensions" \
--server-data-dir "$HOME/.vscode-server/data"
Then open the DSH Sidebar icon in the activity bar (or run DSH Sidebar: Open Agent).
npm ci
npm run typecheck # extension host types
npm test # unit tests (node --test, no extension host needed)
npx playwright install chromium
npm run smoke # HTTP and browser contracts against a real `dsh` on PATH
npm run build # bundles dist/extension.js and dist/bridge.js with esbuild
npm run package # builds and produces dsh-sidebar-<version>.vsix
Press F5 in VS Code to launch an Extension Development Host.
DeepSeek Harness is in developer preview and does ship compatibility-breaking changes. 0.2.0-rc.1 is the
tested CLI and the documented minimum; neither is enforced. The extension no longer probes
dsh --version (there is no src/dsh-version.ts) and never refuses a CLI before launching it.
| dsh-sidebar | DeepSeek Harness | Notes |
|---|---|---|
| 0.5.2 | 0.2.0-rc.1 tested | Preserve the bridge across live client graph updates, use the new Session selection API, and reconnect every window's proxy after a shared restart. Includes browser contract checks. |
| 0.5.1 | 0.2.0-rc.1 tested and documented | Contract smoke and the documented environment moved to DSH 0.2.0-rc.1. |
| 0.5.0 | 0.1.5-rc.2 tested, 0.1.5-rc.1 documented | One DSH server per workspace: a detached keeper is shared by every window and Remote-SSH connection of that folder and reaps the CLI after a 120-second idle grace. Closing-message file mentions open in the editor. |
| 0.4.0 | 0.1.5-rc.2 tested, 0.1.5-rc.1 documented | Direct CLI launch without a version gate; one Extension Host connection ladder that rebuilds the page on a fresh forwarding authority. |
| 0.3.14 | 0.1.5-rc.2 tested, 0.1.5-rc.1 minimum | Extension Host ownership, page connection recovery and history timeout feedback. |
| 0.3.12 | 0.1.5-rc.2 tested, 0.1.5-rc.1 minimum | Newer CLIs start with a warning in the output channel; older ones are refused. |
| 0.3.11 | 0.1.5-rc.2 tested, 0.1.5-rc.1 minimum | First public release on GitHub. |
The protocol this build speaks — the launch URL and its one-time token, the session/list client-request
envelope, the workspace/* order and archive mutations, the boot graph and the sidebar plugin identity — is
not a frozen public API. When a DSH release
changes it, npm run smoke and the CI contract job are what catch it first.
| Setting | Default | Purpose |
|---|---|---|
dsh.embed.command | (empty) | Override the executable used to start the runtime; empty uses dsh from PATH. |
dsh.embed.args | [] | Override the complete argument list passed to the runtime. |
dsh.embed.workspaceFolder | (empty) | Workspace folder path to pin; defaults to the first folder. |
src/runtime.ts — attaches this window to its workspace keeper, publishes the window's own loopback
bridge proxy, detaches on stop or dispose, and rebinds the proxy to a fresh loopback authority on demand
(rotateOrigin). restart() asks the keeper to replace the shared backend.src/runtime-keeper.ts — the detached per-workspace owner of one DSH backend: it launches the configured
command, exchanges the one-time launch token for the browser-session cookie, counts attached Hosts, and
reaps the CLI only after the last one detached and the idle grace expired.src/runtime-client.ts — the Extension Host side of the control protocol: attaches to the keeper named by
the share record, or forks exactly one keeper under a bootstrap lock when that record is missing or stale.src/runtime-workspace.ts / src/process-tree.ts — workspace key, candidate control ports, the 0600
share record and bootstrap lock; private process groups plus observed Linux descendants for cleanup.src/proxy.ts — loopback reverse proxy (HTTP + WebSocket) that injects the auth cookie, rewrites the
boot theme to the VS Code theme, serves the injected bridge script, and binds a fresh port when the page
must be rebuilt (relisten).src/bridge.js — injected into the page: drains the DSH sidebar from the boot graph, pins the workspace,
intercepts tool-path links, delivery cards and drag/drop references, drives the theme through the page's own
ThemeRuntime, and relays the workspace order and archive set for the native tree.src/connection-recovery.js — injected into the page: reports DSH's own connection.state and answers
the host's reconnect-page request; it owns no timers or thresholds.src/recovery-shell.js — the local webview shell: reports shell-alive every three seconds, relays
messages, and renders the host's localised status banner.src/session-panel.ts — native TreeDataProvider reading session/list through the proxy, in the manual
order the page publishes and without archived rows.src/session-actions.ts — the Workspace RPCs behind the tree's reorder and archive actions, plus the pure
order-planning helpers the drag-and-drop controller uses.src/extension.ts — webview shell, message relay, file/diff providers, the command surface and the
single connection-maintenance ladder.The runtime belongs to a canonical workspace folder, not to a window or an Extension Host. The first window or Remote-SSH connection of a folder starts a detached workspace keeper; every later window of the same folder attaches to that keeper and reuses its one backend. Closing a window, losing the SSH transport or replacing the Extension Host therefore does not stop the backend or a running agent — the keeper is independent of all of them. Only after the last attached window has detached does the keeper wait out its idle grace (two minutes) and then stop the CLI. Hiding the sidebar has no effect on the backend.
Windows of different folders get separate keepers, control ports and backends. Two live windows on one folder are no longer a conflict: they share the backend, and a restart replaces that shared backend, interrupting tasks in every window of the folder.
A keeper that is killed is replaced by the next window that attaches, and the replacement reaps the backend its predecessor orphaned. Runtimes from 0.3.12–0.4.0 have no keeper and cannot be adopted: finish or cancel their work and stop the old runtime before reloading. An occupied backend port is still a CLI failure reported through the keeper, not permission to pick another port. Do not remove session lock files; DSH's own session flock remains the final cross-process writer exclusion.
See runtime lifecycle for shutdown guarantees, platform limits and tests.
If startup fails, the Agent view shows a short, selectable diagnosis. It has no buttons: the extension retries the start automatically, and the DSH Sidebar output channel carries the complete runtime output, including the CLI's own failure message.
dsh web reports its own message. Use dsh.embed.command / dsh.embed.args for a
custom launcher, or upgrade dsh with npm install -g @deepseek-ai/dsh.dsh is not on the extension host's PATH. Use dsh.embed.command for an
explicit path, or install it globally on the machine that hosts the folder.~/.dsh/vscode-embed/telemetry.jsonl and publishes
current.json next to it (the most recently activated window); trace rows include Host PID, workspace and runtime identity, while page events carry their page identity. The port in that file answers /status, /logs, /ping and /restart on loopback.The /status response also includes the latest shell heartbeat and the most recent traced event. Periodic
heartbeats stay in memory; only status changes enter the trace. See
page recovery for timings and verification.
The extension uploads nothing. It writes its own JSONL trace under ~/.dsh/vscode-embed/, binds its proxy
and its diagnostic server to 127.0.0.1 only, and never sends a request of its own to any other host: the
only network peers it talks to are the DSH process it started and its own workspace keeper on loopback. The
keeper writes the owner-only (0600) share record under ~/.dsh/vscode-embed/workspaces/; the
browser-session cookie lives in the keeper, is handed to an attached window only over that loopback control
socket after the window presents the record's token, and is injected upstream by the window proxy, so the
browser never receives it. Following a link in the conversation opens VS Code's Simple Browser, which then
loads that URL the way any browser would. Besides its own keeper process, the only external processes it
runs are the dsh CLI you installed and git, the latter to read a file's HEAD content when the
conversation asks for a diff against HEAD.
MIT © 2026 Huanqi Cao. A community extension for DeepSeek Harness, which is maintained by DeepSeek AI.