dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
A Windows system-tray indicator that monitors and controls a local DeepSeek Harness (DSH) web instance — the process started by dsh web
A Windows system-tray indicator that monitors and controls a local
DeepSeek Harness (DSH) web instance — the process started by dsh web
(node .../@deepseek-ai/dsh/lib/bin.js web).
The tray icon is the whole UI: green = running, yellow = starting/stopping, red = stopped/error. Right-click for start / restart / stop / open the Web UI.
中文文档见 README.zh-CN.md。
| Live status | Tray icon colour + tooltip (PID, port, uptime, memory); balloon on state change |
| Lifecycle control | Start / Start as administrator (UAC) / Restart / Stop |
| Open the Web UI | Opens the browser at the authenticated URL (see below) |
| Self-elevation | "Restart indicator as administrator" hands the single-instance mutex over to an elevated copy |
| Three entry points | -Tray, -Once (one-shot status report), or an interactive console menu |
| Configurable logging | Level / directory / rotation via status-indicator.config.json |
| Autostart | Ready-to-use scheduled-task recipe (logon trigger, highest privileges) |
Get-NetTCPConnection)PATHnode_modules\@deepseek-ai\dsh\lib\bin.js# one-shot status report
powershell -NoProfile -ExecutionPolicy Bypass -File .\status-indicator.ps1 -Once
# tray mode
powershell -NoProfile -ExecutionPolicy Bypass -File .\status-indicator.ps1 -Tray
# interactive console menu
powershell -NoProfile -ExecutionPolicy Bypass -File .\status-indicator.ps1
| Parameter | Default | Meaning |
|---|---|---|
-Port | 3000 | Port the indicator uses when it starts DSH |
-DshDir | auto-detected | Directory containing node_modules\@deepseek-ai\dsh |
-Once | Print status once and exit | |
-Tray | Tray mode |
-DshDir is auto-detected in this order:
-DshDir argument$env:DSH_INSTALL_DIR, then $env:DSH_DIRdsh command (e.g. <install>\dsh.cmd) and its parents%APPDATA%\npm\node_modules (global npm installs)If none match, the indicator reports a clear error instead of guessing.
Port note.
-Portonly affects instances the indicator starts itself. If yourdsh webis configured to listen elsewhere, pass the matching-Port, otherwise the indicator will launch its own instance on3000.
UI (tray / console) ──request queue──▶ Worker (single long-lived engine) ──▶ Core (detection / process control)
▲ │
└──────────────────────── StateStore (snapshots) ◀─────────────────────────┘
Start-Process calls run on a background worker engine, so the context menu
is always instantly responsive.operationId that appears in the log.Local\DshStatusIndicatorTray) — there is
no PID file. When elevating, the new copy waits up to 30 s for the old one.dsh web mints a per-process random launch token that lives only in memory
and is printed exactly once at startup:
dsh web: http://127.0.0.1:3080/?token=<43-char-base64url>
Visiting that URL mints a signed HttpOnly cookie (30 days by default, bound to
the host:port authority). Any request without the token or cookie gets
401 dsh web authentication required.
Because the token is never written to disk, the indicator redirects the launched process's stdout to a capture file and parses the URL from it:
.dsh-web-url-*.txt in the project root, at most 5 are
kept, and they are deleted when the instance stops;.dsh-web-url-*.txt is gitignored — never commit it;status-indicator.config.json (created with defaults on first run; changes take
effect on the next start, there is no hot reload):
{
"logging": {
"enabled": true, // false = no I/O and no thread at all
"level": "INFO", // DEBUG / INFO / WARN / ERROR
"directory": "logs", // relative to the project root; absolute paths are rejected
"maxFileSizeMB": 5, // 1-100
"maxFiles": 5 // 1-50
}
}
Invalid values fall back to defaults and are recorded — a broken config never prevents startup. Logging is a low-overhead side channel: an in-memory queue plus a single writer thread, so the UI thread never touches the disk, with a bounded flush on exit.
Run once from an elevated PowerShell:
schtasks /Create /F /TN "dsh-status-indicator" /SC ONLOGON /RL HIGHEST /DELAY 0000:05 `
/TR "powershell.exe -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File \"C:\path\to\status-indicator.ps1\" -Tray -Port 3000"
/RL HIGHEST runs the tray with administrator rights, so starting DSH does not
raise a UAC prompt. Remove it with schtasks /Delete /F /TN "dsh-status-indicator".
All suites are isolated: they never touch a real, already-running DSH instance.
powershell -NoProfile -ExecutionPolicy Bypass -File .\test\run-lifecycle-tests.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\test\run-logging-tests.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\test\run-token-url-tests.ps1
| Suite | Covers |
|---|---|
run-lifecycle-tests.ps1 | Start/verify, stop/verify, restart, start failure → ERROR, port-conflict diagnostics. Uses a fake Harness (test\dsh\...\bin.js) and a process filter restricted to that fake, so real processes are never matched. |
run-logging-tests.ps1 | Logging on/off, invalid-JSON fallback, bad level, absolute-path rejection, rotation, resume. |
run-token-url-tests.ps1 | Launches a real DSH on a spare port (-TestPort, default 3999), asserts the token URL is captured, and verifies bare URL → 401 / token URL → 303. Cleanup only kills PIDs on that test port. |
Expected results: 14/14, 12/12, 9/9.
| Symptom | Cause / fix |
|---|---|
dsh web authentication required in the browser | The plain URL was opened. Let the indicator start/restart the instance so it can capture the token, or open the URL printed by dsh web once to set the cookie. |
| DSH directory not found | Auto-detection failed. Pass -DshDir, or set DSH_INSTALL_DIR. |
| Tray icon does not appear | Another copy holds the single-instance mutex — check the log; a duplicate copy exits after 30 s. |
| Status stays red although DSH is running | DSH listens on a port outside the candidate set (-Port, 3000, 3080). Start the indicator with the matching -Port. |
| Chinese text renders as garbage | The script must stay UTF-8 with BOM; re-save with a BOM after editing. |