dsh-at-file
FSMargoo/dsh-at-fileCodex 风格的 `@file` 文件引用,输入框里直接搜索并引用工作区文件。
在 DeepSeek Harness Web 界面加一个可拖动的电源胶囊:实时状态点,加上重启与结束两个动作;重启交给脱离终端的辅助进程,等端口释放后按原启动命令重新拉起。
A DeepSeek Harness Web plugin: one draggable power pill in the GUI, with a live status dot
and restart / stop actions for the running dsh web service.
Host-only, zero dependencies, no build step.
dsh web keeps running until something stops it. A deployment that wraps it in a watchdog
usually waits out an idle window before tearing the server down, so the port stays occupied for
a while after the last browser tab closes, and a relaunch in that window re-opens a page whose
server is about to disappear.
This plugin puts both actions where the user already is — one pill in the Web GUI, with a dot that says whether the host is answering.
A small translucent pill sits in the configured corner (bottom-right by default).
GET every 5 seconds and costs no model tokens.restart: false and a press stops outright, with no menu at all.localStorage and restored on the next load.The plugin is host-only. No client bundle is built and no @deepseek-ai/* package is
imported: a plugin installed with link: is resolved by Node to its real path, where the
harness packages are not reachable. It uses two extension points the Web carrier already
exposes:
| Extension point | Used for |
|---|---|
webServer.tapIndex() | injecting the pill's markup, CSS, and script into index.html |
webServer.register() | serving /dsh-power-button/status, /restart, and /stop |
Stopping calls the launcher's ctx.appExit — the same bounded shutdown path Ctrl+C uses:
dispose the application tree, then let the process exit. That path only ends the process if the
event loop actually drains, so the plugin also arms an unreferenced 2-second watchdog: it
never delays a clean exit, and it guarantees the process is gone even when another plugin is
still holding a handle.
Restarting cannot be done by the host, because the host is the thing going away. The restart route spawns a detached helper — the same Node binary running an inline module — which
The helper outlives the host (detached + stdio: "ignore" + unref()), so the relaunch
survives the shutdown that triggered it.
Measured on Windows 11 / Node 24: a stop releases the port ~0.2–0.5 s after the POST returns 200; a restart brings the port back in a few seconds, and the failure mode is safe — if the helper cannot be spawned, the route answers 500 and the service is left running.
All three routes require every one of:
x-dsh-power-button: stop — a cross-origin page cannot send it
without a CORS preflight this server never approves, so no random website can restart or
stop your server;Host (127.0.0.1 / localhost / [::1]), which closes the
DNS-rebinding variant;Origin, when the request carries one, matching that Host.Anything else is 403. status answers only GET/HEAD; stop and restart answer
only POST — a non-matching method is 405.
Nothing outside the profile is touched: the restart helper runs the same boot invocation this
process was started with, or exactly the restartCommand you configured.
Every key is optional. Set them on the plugin row:
`@yaml
By default the helper resumes this invocation — the same Node binary, script, and arguments. That is the only thing the plugin can know for certain, and it means a relaunched host has no wrapper watching it: it stays up until you stop it.
If your deployment is started by a launcher that must come back too — for instance one with its
own idle watchdog — point restartCommand at it and let it own the browser:
`@yaml
@sh dsh plugin --profile web add dsh-power-button @
Restart dsh web afterwards: a plugin change never reaches an already-running process.
@sh node --test test/plugin.test.js @
No test dependencies. The injected page script is executed for real against a hand-built DOM —
press versus drag, the movement threshold, clamping, persistence, the menu, the restart action,
and the status poll — and the routes are driven through fake node:http request/response
pairs, including the compression path that silently drops res.end callbacks. The detached
helper's source is syntax-checked as ESM so a broken relaunch cannot ship.
MIT