前言¶
DeepSeek Harness 的 dsh web 会常驻运行,直到进程被显式停止。若外层用 watchdog 一类包装,往往在最后一个浏览器标签关闭后仍要等一段空闲窗口才真正回收服务,端口会空占一段时间;在这段时间里再次打开页面,可能连上的是即将被关掉的实例。
在 Web 界面里直接看到存活状态,并一键结束或重启本机上的 dsh web,是日常开发里很实际的需求。下面介绍社区插件 dsh-power-button(维护者 Neptune810,分类:客户端):在 GUI 里放一颗可拖拽的「电源」胶囊,带实时状态点,并提供重启与结束服务操作。
这是什么¶
dsh-power-button 是仅运行在宿主(host)侧的 DSH Web 插件:无额外依赖、无构建步骤。它在 Web 载体页注入一颗半透明胶囊按钮,通过同源轮询反映主机是否仍在应答,并通过宿主路由执行 结束服务(Stop) 与 重启服务(Restart)。
插件仓库:https://github.com/Neptune810/dsh-power-button
社区目录页:https://www.skillhub.cn/plugins/Neptune810/dsh-power-button
核心功能¶
界面与交互¶
默认在视口右下角(可配置)显示小胶囊:
- 状态点:绿色表示最近一次存活探测得到应答,红色表示未应答。探测为同源
GET,默认每 5 秒一次,不消耗模型 token。 - 点击胶囊:弹出菜单,含「重启服务 (Restart)」与「结束服务 (Stop)」。再次点击胶囊或点击页面其他区域关闭菜单。若配置
restart: false,单击直接结束,无菜单。 - 拖拽:鼠标或触摸可移动位置,写入
localStorage并在下次加载恢复。指针移动超过 4px 视为拖拽,后续误触的 click 会被吞掉,避免拖拽误触发操作。位置限制在视口内,窗口缩小时会重新 clamp。胶囊挂在 React 根之外,应用重渲染不会把它卸掉。
宿主侧行为¶
插件不构建客户端 bundle,也不 import @deepseek-ai/* 包;通过 Web 载体已有扩展点工作:
| 扩展点 | 用途 |
|---|---|
webServer.tapIndex() |
向 index.html 注入胶囊的 markup、CSS、脚本 |
webServer.register() |
提供 /dsh-power-button/status、/restart、/stop |
结束服务 走启动器的 ctx.appExit(与 Ctrl+C 相同的 bounded shutdown):先 dispose 应用树再退出进程。若事件循环仍被其他插件占用,插件还会设置 2 秒、unreferenced 的 watchdog,不拖慢正常退出,又保证进程最终结束。
重启服务 不能在即将退出的宿主进程内完成。/restart 会 spawn 一个 detached 的 Node 辅助进程(同 Node 二进制运行内联模块),在宿主消失且端口不再应答后,用记录下的启动命令与环境、工作目录重新拉起;可选在端口恢复应答后自动打开页面。辅助进程 detached + stdio: "ignore" + unref(),因此能在触发 shutdown 的宿主退出后继续完成 relaunch。README 在 Windows 11 / Node 24 上测得:Stop 在 POST 返回 200 后约 0.2–0.5 s 释放端口;Restart 数秒内端口恢复;若辅助进程 spawn 失败,路由返回 500,服务保持运行。
安全¶
三条路由均要求同时满足:
- 自定义请求头
x-dsh-power-button: stop(跨站页面无法在无 CORS 预批的情况下带上,本服务不批准此类预检); Host为 loopback(127.0.0.1/localhost/[::1]);- 若请求带
Origin,须与上述 Host 一致。
否则 403。status 仅 GET/HEAD;stop 与 restart 仅 POST,方法不符为 405。重启辅助进程只执行本进程当时的启动调用,或你在配置里指定的 restartCommand,不改动 profile 其他部分。
安装与启用¶
在 Web profile 下添加插件:
dsh plugin --profile web add dsh-power-button
修改插件列表后需 重新启动 dsh web,已运行进程不会热加载插件变更。
当前 package 版本为 0.3.0,许可证 MIT,要求 Node >= 20。
配置¶
各项均为可选,写在插件行的 config 下。示例(摘自 README):
- insert:
- id: power-button
name: dsh-power-button
config:
label: 结束服务 # 胶囊文案与 tooltip
position: bottom-right # 初始角:bottom-right 或 bottom-left
draggable: true # false 则固定在该角
status: true # false 去掉状态点并停止轮询
statusPollMs: 5000 # 存活轮询间隔,最小 1000
restart: true # false 去掉重启项且无菜单(单击即停)
restartCommand: [] # argv;空则复用本次启动命令
restartOpenBrowser: true # false 表示你的命令会自行开浏览器
restartWaitMs: 30000 # 辅助进程等待端口的最长时间
enabled: true # false 则不注入任何 UI
默认重启会 复用当前这次 dsh web 的 Node 可执行文件、脚本与参数,relauch 后没有外层 launcher 盯着,会一直跑到你再次停止。若部署由带 idle watchdog 的 launcher 启动,应把 restartCommand 指回 launcher,并视情况设 restartOpenBrowser: false:
- insert:
- id: power-button
name: dsh-power-button
config:
restartCommand:
- 'C:\path\to\YourLauncher.exe'
restartOpenBrowser: false
典型用法¶
- 按上一节安装并重启
dsh web,打开 Web GUI,确认右下角(或配置角)出现胶囊与状态点。 - 需要干净停服、立刻释放端口:打开菜单选「结束服务」,或设
restart: false后单击胶囊。 - 需要同配置原地再起:选「重启服务」,等待端口恢复;若用自定义 launcher,先配好
restartCommand。 - 把胶囊拖到不挡操作的位置;位置会保存在浏览器
localStorage。
仓库内可用以下命令跑插件测试(无额外测试依赖):
node --test test/plugin.test.js
适用场景与注意¶
适合在本机或可信 loopback 环境跑 dsh web、希望从浏览器里确认服务是否还活着、并快速 Stop/Restart 的开发者。插件以 当前 dsh 进程的权限 运行,结束与重启会影响整台机器上的该 Web 服务实例;安装前建议阅读源码与 MIT 许可证,确认路由与 header 约束符合你的威胁模型。
DSH 生态强调「一切皆插件」;SkillHub 等社区目录独立于 DeepSeek / 幻方,并非官方应用商店。本插件星标与维护节奏以 GitHub 与目录页为准。
结尾¶
dsh-power-button 把 Stop/Restart 和存活指示放在你已经打开的 Web GUI 里,host-only、零依赖,适合解决 dsh web 常驻与端口空占带来的操作不便。详情与更新见 GitHub 仓库 与 SkillHub 目录页。