DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

Aclguh /

Aclguh/dsh-web-close

Verified

DeepSeek-Harness插件,用于关闭dsh的web进程

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: master@d73cf9b3

dsh-web-close —— DSH Web 关闭按钮

DSH(DeepSeek Harness)Web 界面上的常驻关闭按钮:半透明红色、SVG 手绘电源图标、 可拖动并记忆位置,点击后弹出视口居中的二次确认(左「取消」灰 / 右「确认关闭」红), 确认后优雅关闭当前正在运行的 DSH 进程,并尝试关掉当前这个 DSH 页面 (只关本页,不会关掉浏览器或其他窗口)。

标准 DSH 插件包,通过 dsh plugin 安装与卸载,随 dsh web 每次启动自动加载。

特性

<<<<<<< HEAD

  • 常驻自启:标准 DSH bundle 插件,装一次,之后每次启动都在
  • 半透明红外观:rgba(220,38,38,.42) + 毛玻璃 + 红色描边光晕,悬停加深
  • SVG 手绘图标:电源符号、警告三角、叉号全部为内联 SVG,不含任何图片资源
  • 可拖动 + 位置记忆:默认落在视口 top: 1234px / left: 306px (等价于 inset: 1234px auto auto 306px);拖到哪就在哪,写入 localStorage, 刷新或重开浏览器后原样恢复;按当前视口夹取,窗口变小也不会跑到屏幕外
  • 二次确认弹窗:视口居中,左「取消」灰、右「确认关闭」红,并显示将要关闭的 PID 与地址
  • 优雅关闭:不是 kill -9,而是先卸载整棵插件树再退出(见下)
  • 顺便关掉本页面:关闭请求被接受后自动 window.close() 当前标签页; 浏览器出于安全策略拒绝时,弹窗里会出现「关闭本页」按钮,退而把本页置为 about:blank。 全程只作用于当前这一个标签页,其他窗口与标签页不受影响
  • 跨平台、零依赖:宿主侧只用 Node 内置模块,浏览器侧是纯原生 DOM;

  • 常驻自启:标准 DSH bundle 插件,装一次,之后每次启动都在
  • 半透明红外观:rgba(220,38,38,.42) + 毛玻璃 + 红色描边光晕,悬停加深
  • SVG 手绘图标:电源符号、警告三角、叉号全部为内联 SVG,不含任何图片资源
  • 可拖动 + 位置记忆:拖到哪就在哪,写入 localStorage,刷新或重开浏览器后原样恢复; 按当前视口夹取,窗口变小也不会跑到屏幕外
  • 二次确认弹窗:视口居中,左「取消」灰、右「确认关闭」红,并显示将要关闭的 PID 与地址
  • 优雅关闭:不是 kill -9,而是先卸载整棵插件树再退出(见下)
  • 跨平台、零依赖:宿主侧只用 Node 内置模块,浏览器侧是纯原生 DOM;

e0f3bb049138f465ae5c900a80e6f292f6f4dfb3 Windows / macOS / Linux 行为一致,没有 PowerShell、没有构建步骤、没有运行时依赖

安装:从 GitHub 克隆安装

git clone https://github.com/Aclguh/dsh-web-close.git
cd dsh-web-close
dsh plugin --profile web add link:.

要点:

  • link:. 表示链接当前目录——仓库根目录本身就是插件包。
  • ⚠️ 不要写成 link:.\dsh-web-close 这类带子目录的路径,那样会装成普通依赖而不是插件, 重启后按钮不会出现。
  • 成功后 dsh plugin 会自动把 dsh-web-close 写进 profile 的 dsh.profile.bundles, 不需要手工改配置。
  • 装完必须重启 dsh web,然后刷新浏览器。
  • 如果之后移动了源码目录,要重新执行一次 add link:<新路径>;若提示冲突, 先 dsh plugin --profile web remove dsh-web-close 再重新 add。

卸载

dsh plugin --profile web remove dsh-web-close

然后确认 profile 的 dsh.profile.bundles 里不再有 "dsh-web-close"(没有就无需处理), 最后重启 dsh web。

环境要求

  • 已安装 DSH,且能正常执行 dsh web
  • pnpm(dsh plugin 会把参数转发给 pnpm;缺失时先 npm install -g pnpm)
  • 本插件只对 web profile 有意义(它依赖 DSH 的 Web 服务器服务)
  • 没有其他依赖:不需要额外 npm 包、不需要构建工具、不需要任何 API Key

给 AI 助手的安装说明

如果想让另一个 DSH / AI 助手代装,把下面这段直接发给它:

请帮我安装 DSH 插件 dsh-web-close,来源是 GitHub 仓库 Aclguh/dsh-web-close。

步骤:
1. 确保 pnpm 可用(没有就先执行 npm install -g pnpm)
2. git clone https://github.com/Aclguh/dsh-web-close.git
3. 进入克隆出来的 dsh-web-close 目录,执行:
   dsh plugin --profile web add link:.
   (仓库根目录就是插件包,不要写成 link:.\dsh-web-close 这种带子目录的路径)
4. 重启 dsh web,然后刷新浏览器

安装后请验证:
- dsh --profile web --dump-config 的输出里能看到 - id: dsh-web-close
- 浏览器里出现半透明红色圆形按钮(默认在视口 top 1234px / left 306px)
- curl http://127.0.0.1:3080/dsh-web-close/info.json 返回含 "ok":true 的 JSON

它是怎么关闭 DSH 的

插件运行在 DSH 宿主进程内部,也就是承载 Web 服务与 Agent 的那个 node 进程本身。 因此它不需要去别的进程里"找到它再杀掉",而是调用 DSH 自己的有界优雅关闭:

顺序 路径 行为
1 ctx.get('appExit')(0) DSH 启动器通过 provideCmdline() 提供的退出请求 → shutdown.shutdown(0):先 dispose 整棵插件树(所有插件的 disposer 都会执行),再设 exitCode = 0 让 Node 自然退出
2 process.emit('SIGINT') 命中 DSH 自己注册的 process.on('SIGINT') → shutdown.interrupt(130),同样先 dispose 再退出
3 process.exit(0) 兜底强制退出

appExit 是 ctx.provide() 提供的裸值,不在 Service 目录里;因此本插件刻意不把它写进 inject(那样会有让整行永远停在 waiting for appExit 的风险),而是运行时用 ctx.get() 取值,并带上表里的降级链。

⚠️ Web 服务与 Agent 宿主是同一个 node 进程,所以关闭的是整个 DSH,当前所有会话都会中断—— 这正是二次确认存在的原因。

<<<<<<< HEAD 关闭请求被接受后,浏览器侧还会做最后一件事:关掉当前这一个标签页。 它只调 window.close(),不碰 window.opener、不碰其他窗口;浏览器按安全策略拒绝时, 退化为把本页替换成 about:blank。

=======

e0f3bb049138f465ae5c900a80e6f292f6f4dfb3

目录结构

dsh-web-close/
├── package.json        # 包声明;dsh.bundle.patch 指向 cordis.patch.yml
├── cordis.patch.yml    # bundle patch:把 id/name 为 dsh-web-close 的一行插入配置树
├── lib/
│   ├── index.js        # 宿主半边:HTTP 路由 + tapIndex 注入 <script>
│   └── widget.js       # 浏览器半边:原生 DOM 的按钮与确认弹窗
├── README.md
└── LICENSE

验证

配置层——确认插件行被组合进 profile:

dsh --profile web --dump-config

输出中应能看到:

# == dsh-web-close
- id: dsh-web-close
  name: dsh-web-close

服务层——需要 DSH 正在运行。端口按你自己的替换(DSH 默认 3080):

curl http://127.0.0.1:3080/dsh-web-close/info.json
# {"ok":true,"pid":12345,"url":"http://127.0.0.1:3080","profile":null,"uptimeSec":438,"inProcess":true}

curl -I http://127.0.0.1:3080/dsh-web-close/widget.js
# HTTP/1.1 200 OK
# Content-Type: application/javascript; charset=utf-8

界面层——重启并刷新后,页面里出现半透明红色圆形按钮 (默认在视口 top 1234px / left 306px)。

DSH 的 HTML 路由自身带访问鉴权(直接 curl 根路径会得到 401),但插件注册的同源路由不受影响, 所以上面两条 curl 可以直接用。

使用

  • 拖动:按住按钮拖到任意位置。位移超过 4px 才判定为拖动,因此不会误触发点击。
  • 位置记忆:松手即写入 localStorage,键名 dsh-web-close-pos(结构 { v: 2, left, top })。 想恢复默认位置(top 1234 / left 306),在浏览器控制台执行:
    localStorage.removeItem('dsh-web-close-pos')
    
    然后刷新页面。位置按当前视口夹取,所以窗口比 1234px 矮时按钮会被收到可视区域内。
  • 关闭:点击按钮 → 弹窗显示目标进程 node.exe · PID … · http://127.0.0.1:… → 点「确认关闭」。约 0.9 秒后 DSH 开始退出,随后自动尝试关闭本页面。 若浏览器拒绝脚本关闭(只允许关闭脚本打开的窗口),弹窗会给出「关闭本页」按钮兜底。
  • 点「取消」、点弹窗外的遮罩、或按 Esc 都会关闭弹窗,不会执行任何操作。

路由

宿主半边在 DSH 的 Web 服务器上注册三个同源路由:

路由 方法 说明
/dsh-web-close/widget.js GET 浏览器半边脚本。每次请求都重新读盘,所以改完 lib/widget.js 只需刷新页面
/dsh-web-close/info.json GET 返回将被动到的进程:process.pid 与浏览器自己的 Host 头
/dsh-web-close/shutdown POST 接受关闭请求,延迟 0.9 秒后触发优雅关闭(其他方法返回 405)

widget.js 由 ctx.webServer.tapIndex() 以 <script defer> 注入 index.html,并带重复注入保护。

/shutdown 是用 fetch(..., { keepalive: true }) 发出的,所以即使标签页随后立刻被关掉, 请求也一定能送达。

常见问题

  • 按钮不出现
    1. 确认 dsh plugin --profile web add 成功,且 dsh --profile web --dump-config 里能看到 - id: dsh-web-close;
    2. 确认重启过 dsh web——插件只在启动时加载,热改配置不会生效;
    3. 重启后按 Ctrl/Cmd + Shift + R 强制刷新,避开浏览器缓存。
  • 改了默认位置后按钮没动:localStorage 里存的是旧结构(v: 1)坐标,会被自动作废并回落新默认位置; 若想彻底清干净,执行 localStorage.removeItem('dsh-web-close-pos') 再刷新。
  • 拖动后位置没保留:无痕/隐私模式下 localStorage 不可用,这时只在本次会话内记忆位置。
  • 点了「确认关闭」但页面没自动关闭:浏览器的安全策略只允许脚本关闭"由脚本打开的"窗口, 普通标签页会被忽略。这时弹窗会出现「关闭本页」按钮(置为空白页),或直接按 Ctrl / ⌘ + W。 DSH 进程本身不受影响,已经退出或正在退出。
  • 点了「确认关闭」但没退出:查看 dsh web 所在终端的输出,关闭时会打印一行 [dsh-web-close] graceful shutdown requested via appExit(或 via SIGINT)。
  • 端口不是 3080:把 curl 命令换成你自己的端口即可;界面里显示的地址来自浏览器实际请求, 始终是正确的。
  • 改了代码不生效:改 lib/widget.js 只需刷新页面(路由每次重新读盘); 改 lib/index.js(宿主半边)需要重启 dsh web。
  • 会和别的插件冲突吗:本插件只占用 /dsh-web-close/* 三个路由和一个 id: dsh-web-close 的配置行。与同生态插件的 tapIndex 注入是叠加关系, 例如可与 dsh-whale-widget 同时使用,两个 <script> 会并存于页面底部。

许可证

本项目基于 MIT License 开源,详见 LICENSE。

—/ 5

No ratings yet

Verified DSH bundle

Commit d73cf9b3fd56

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout