dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
Embed DeepSeek Harness (dsh) web GUI in VS Code — zero-config auto-start, workspace follow, self-healing. /在 VS Code 里内嵌 DeepSeek Harness 网页版,零配置自动启动、多工作区跟随、掉线自愈。
A Claude Code-style native DSH sidebar for VS Code: a self-written native
front-end (no iframe) that reuses your existing dsh web service
(127.0.0.1:3080 by default) and ~/.dsh — no second gateway, no server changes.
Unofficial community extension. Not affiliated with DeepSeek.
Harness compatibility: 0.6.0 speaks the 0.1.6 wire (Typert API Gateway: cookie-authenticated
/api/<ns>/<method>, oneremote.muxWebSocket, durable events plus process-local assistant frames). For DeepSeek Harness 0.1.0–0.1.5 use release 0.5.0; the two wires are not interchangeable.
Ctrl+Alt+D./compact, Markdown + code blocks.POST /api/<ns>/<method> with named args,
a browser-session cookie minted from the launch token, and one /api/remote.mux
socket carrying every stream (session follow, workspace baseline, $events) —
see docs/protocol.md.From a released .vsix:
code --install-extension dsh-webview-0.6.0.vsix
Or build it yourself (run in the repo root):
npx @vscode/vsce package
pwsh -File test\fix-vsix.ps1 # repairs vsce's UTF-8 mangling of package.json
code --install-extension dsh-webview-0.6.0.vsix
⚠️ Known issue: on some Windows environments
vsce packagere-encodes the Chinese text inpackage.jsonas GBK mojibake and can even break the JSON. Always runtest\fix-vsix.ps1after packaging.
On startup the extension probes dshWeb.port (default 3080) and attaches if a
dsh instance responds. Otherwise it starts one, trying in order:
dshWeb.command → dshWeb.checkout → dsh on PATH → npx @deepseek-ai/dsh.
The server runs with cwd = the first workspace folder and DSH_HOME pinned
to ~/.dsh (identical to attach — never isolated).
| Setting | Default | Meaning |
|---|---|---|
dshWeb.port | 3080 | Port to attach to or start on |
dshWeb.attachExisting | true | Reuse a running instance instead of starting a new one |
dshWeb.spawnIfMissing | true | Start a server when none is running |
dshWeb.checkout | "" (auto) | Optional checkout path (launches apps/cli/lib/bin.js) |
dshWeb.command | "" | Full command override, e.g. pnpm dsh |
dshWeb.extraArgs | [] | Extra arguments, e.g. --trusted-host |
dshWeb.attachWaitSeconds | 30 | Seconds to wait for a launcher before starting a server of our own |
dshWeb.takeoverAfterSeconds | 45 | Seconds an attached server may stay silent before we take the port over |
dshWeb.nodeMaxOldSpaceMb | 8192 | --max-old-space-size for the node we launch (0 = Node's default) |
dshWeb.nodeArgs | [] | Extra flags for the node executable itself (checkout launcher) |
dshWeb.followWorkspace | true | Restart self-started server when the first folder changes |
dshWeb.stopOnExit | true | Stop a self-started server when VS Code exits |
Troubleshooting: Output → DSH (logs connection and protocol traffic).
Two independent root causes, both fixed by the bundled one-click fix-dsh.cmd:
VS Code caches its extension scan in .vscode\extensions\extensions.json. If a new
version is installed by deleting the old folder, VS Code still looks for the old path
at startup → ENOENT → the extension is marked broken and the new version in the same
folder is never discovered (hence no icon).
Fix: test\fix-cache.js — rewrites the cache entry to the new path, drops the
profile-level scan caches (forcing a full rescan), and repairs the placeholder icon
path. Backups are created automatically.
VS Code 1.136 stores auxiliary-bar container icons (title-bar / right-edge strip) in
global storage workbench.auxiliarybar.pinnedPanels; the Chat tab's persistence
lives there too. Patching only the per-workspace state is ineffective, and edits made
while VS Code is running get overwritten on exit.
Fix: test\fix-state.js — removes Chat from the global pinned list, registers
dsh-aux, hides the Chat view across all workspace DBs, and backs up every
state.vscdb (.bak-dsh); idempotent.
fix-dsh.cmd on the Desktop (it refuses to run while VS Code is open);node test/respond-wire-verify.js # permission/question answer wire shape (14 checks, headless)
node test/approval-card-verify.js # approval card rendering + dedup (12 checks, jsdom)
node test/real-launch-verify.js # spawns the real dsh web server through the launch chain
node test/spawn-verify.js # launch-chain (checkout / dsh CLI / npx) checks
approval-card-verify.js runs the real webview/app.js in jsdom and drives it
uith the same host messages the extension sends. It pins the field-name contract
behind the duplicate-card bug: session-log events carry the approval id as
data.id, while server-request frames carry it as approvalId; reading only the
latter makes the id undefined, so the log card and the replayed frame render as
two identical cards and approval/decided never settles either. It needs jsdom,
so point DSH_CHECKOUT_NODE_MODULES at a checkout that has one, e.g.
$env:DSH_CHECKOUT_NODE_MODULES = '<checkout>\node_modules'.
respond-wire-verify.js is the regression guard for the sidebar's permission
buttons: it stands up a fake dsh gateway, activates the extension against it,
pushes an approval/* and a question/* frame into the sidebar webview, and
asserts the POST /api/respond envelope. The gateway routes client-responses by
the echoed rpcId and then validates the payload against
approvalResponsePayloadSchema / questionResponsePayloadSchema, both of which
require sessionId; a wrong shape is rejected with {accepted:false} and
surfaces to the user as server rejected response to undefined.
MIT — see LICENSE.