← Back to home@moxingovo

dsh-web-panel

Claude Code-style native DeepSeek Harness sidebar for VS Code: self-written chat UI (no iframe) reusing the existing dsh web service — workspace-synced sessions, sandbox-permission/model/reasoning pickers, context ring. / VS Code 里的 Claude Code 风格 DeepSeek Harness 原生侧边栏:自写聊天 UI(无 iframe),复用现有 dsh web 服务;工作区会话同步、沙箱权限/模型/推理档选择、上下文占用环。

Stars
1
Language
JavaScript
Created
Aug 14, 2026
Updated
Sep 18, 2026

Introduction

DSH Web Panel

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>, one remote.mux WebSocket, 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.

  • Entry points (same as Claude Code): the DeepSeek Harness icon (DeepSeek blue) in the top-right auxiliary bar — click to summon the chat panel; the status-bar DSH item shows server state and toggles the panel; Ctrl+Alt+D.
  • Sessions: current-workspace sessions only — create / switch / archive / rename / fork; the context meter shows real server-side token data.
  • Model & preset: model + reasoning-effort pickers; preset switching is blank-session-only (locked once the conversation starts — a server constraint).
  • Capabilities: streaming replies, stop, tool cards / approval cards / todos / timeline, image attachments (vision), /compact, Markdown + code blocks.
  • Protocol: 0.1.6 Typert gateway — 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.

Install

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 package re-encodes the Chinese text in package.json as GBK mojibake and can even break the JSON. Always run test\fix-vsix.ps1 after packaging.

Zero-config launch

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).

Settings

SettingDefaultMeaning
dshWeb.port3080Port to attach to or start on
dshWeb.attachExistingtrueReuse a running instance instead of starting a new one
dshWeb.spawnIfMissingtrueStart 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.attachWaitSeconds30Seconds to wait for a launcher before starting a server of our own
dshWeb.takeoverAfterSeconds45Seconds an attached server may stay silent before we take the port over
dshWeb.nodeMaxOldSpaceMb8192--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.followWorkspacetrueRestart self-started server when the first folder changes
dshWeb.stopOnExittrueStop a self-started server when VS Code exits

Troubleshooting: Output → DSH (logs connection and protocol traffic).

Troubleshooting: missing top-right icon / persistent "Chat" tab

Two independent root causes, both fixed by the bundled one-click fix-dsh.cmd:

Cause 1: the extension scan cache points at a deleted old-version folder

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.

Cause 2: auxiliary-bar container icons / Chat tab persistence live in global storage

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.

Usage

  1. Fully exit VS Code (all windows, including minimized);
  2. Double-click fix-dsh.cmd on the Desktop (it refuses to run while VS Code is open);
  3. Reopen VS Code → the blue harness icon appears top-right, Chat is gone.

Development

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.

License

MIT — see LICENSE.