Bundle
dsh-web-restart
Add a Restart DSH button to the DeepSeek Harness WebUI. The button stops the dsh web process; an external supervisor (e.g. macOS launchd LaunchAgent) restarts it automatically so the UI comes back.
- Source
- QIN-SMART
- stars
- 2 stars
- License
- MIT
- Updated
- Updated 20 hours ago
Readme
# dsh-web-restart
在 DeepSeek Harness 的 **WebUI 里加一个「重启 DSH」按钮**,并配好 macOS 上
**把 DSH 变成图标启动 + 崩溃/被杀后自动重启** 的基础设施。
- **WebUI 重启按钮**:侧边栏底部的「⇄ 重启 DSH」按钮。点击后全屏遮罩提示
"正在重启 DSH…",进程退出后由外部守护(launchd)自动拉起,页面自动刷新恢复。
- **外部守护**:因为 `dsh web` 是单 Node 进程,进程一退出 UI 就断线。要让
"重启后能回来",必须由 **外部守护** 在进程退出后把 `dsh web` 重新拉起。
本仓库提供 macOS launchd LaunchAgent(`launcher/macos/`),崩溃/退出自动拉起,
可设登录自启。
> 插件本身无法在死后自举 —— 重启按钮与外部守护是配套的两半,缺一不可。
---
## 功能
| 能力 | 说明 |
|---|---|
| WebUI 重启按钮 | 侧边栏底部,两段式确认(防误触),触发后全屏遮罩 + 轮询自动恢复 |
| 双通道触发 | 首选 DSH 官方 RPC(`remote.commands.execute("/restart")`),回退同源 `fetch` |
| launchd 守护 | `KeepAlive` 自动拉起崩溃/退出的进程,登录自启 |
| 启动台图标 | AppleScript 编译的 `.app`,点击启动 + 打开浏览器 |
| 可选 token | host 端点支持 `Authorization` / `X-Dsh-Restart-Token` 校验 |
---
## 安装到你的 DSH profile
### 方式 A:从 GitHub 安装(推荐)
在你的 profile 目录(`~/.dsh/profiles/web/`)里:
```sh
cd ~/.dsh/profiles/web
pnpm add "dsh-web-restart@github:<你的用户名>/<仓库名>"
```
然后在 `~/.dsh/profiles/web/package.json` 的 `dsh.profile.bundles` 数组末尾加上:
```jsonc
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"dsh-web-restart" // ← 加这一行
]
}
}
```
重启 `dsh web` 后生效。
### 方式 B:本地 link(开发用)
```sh
cd ~/.dsh/profiles/web
pnpm add "link:/绝对/路径/dsh-web-restart"
```
同样在 `bundles` 里加上 `"dsh-web-restart"`,重启生效。
> 想改插件默认配置(`mode` / `token` / `flushMs` / `enableCommand`)?
> 在 profile 的 `cordis.patch.yml` 里覆盖:
> ```yaml
> - id: web-restart
> name: dsh-web-restart
> token: my-secret
> ```
---
## macOS:launchd 守护 + 启动台图标
### 1) 安装 launchd 守护(自动拉起 + 登录自启)
```sh
chmod +x launcher/macos/*.sh
launcher/macos/dsh-web-control.sh install
```
常用命令:
| 命令 | 作用 |
|---|---|
| `dsh-web-control.sh status` | 查看 launchd 状态 |
| `dsh-web-control.sh restart` | 手动重启 |
| `dsh-web-control.sh stop` / `start` | 停 / 启(停止不解除自启) |
| `dsh-web-control.sh uninstall` | 卸载 |
日志:`~/.dsh/dsh-web.launchd.log` 与 `~/.dsh/dsh-web.launchd.err.log`。
> 细节:安装脚本会把 `dsh-web-start.sh` 复制到 `~/Library/Application Support/dsh-web/`
> 再交给 launchd —— 因为 macOS TCC 隐私保护下 launchd **无法读取 `~/Documents`
> 等目录里的脚本**。脚本会自动探测 `node` 与 `dsh` 的路径(nvm / PATH),
> 也可用 `NODE_BIN` / `DSH_ENTRY` / `DSH_HOME` 环境变量覆盖。
### 2) 启动台 / Dock 图标
用仓库里的 AppleScript 编译一个 App(macOS 自带 `osacompile`):
```sh
mkdir -p build
osacompile -o build/DSH.app launcher/macos/DSH-Web-Launcher.applescript
# (可选)替换图标:准备 dsh.icns 后
# cp dsh.icns build/DSH.app/Contents/Resources/
# /usr/libexec/PlistBuddy -c "Set :CFBundleIconFile dsh" build/DSH.app/Contents/Info.plist
cp -R build/DSH.app /Applications/
```
也可以手动做一个 Automator 应用:新建「应用程序」→ 运行 shell 脚本:
```sh
~/Library/Application Support/dsh-web/dsh-web-start.sh
sleep 3
open http://127.0.0.1:3080
```
另存为 DSH.app 拖到 Dock / 启动台即可。图标素材可自行从
`http://127.0.0.1:3080/favicon.svg`(DSH 官方鱼形 logo)制作。
---
## 工作原理
### host 端(`index.mjs`)
- 通过 `webServer` 服务注册同源 HTTP 端点 **`POST /api/_dsh/restart`**
(浏览器与 server 同源,`fetch` 直接可用,不依赖活跃会话)。
- 端点命中 → 返回 `202` → 稍作延迟让响应落盘 → 执行退出:
- `mode: "exit"`(默认):`process.exit()`,交给 launchd `KeepAlive` 拉起。
- `mode: "exec"`:同进程内 `spawn` 一个新 `dsh web` 并 `unref`,旧进程退出,
适合没有外部守护、从终端手动跑的场景。
- 可选 `token` 校验;同时注册 `/restart` slash 命令(`enableCommand`)。
### client 端(`lib/client.js`)
- 注入侧边栏底部槽 **`sidebar.footer.action`** 渲染「⇄ 重启 DSH」按钮。
- 两段式确认防误触;触发后全屏遮罩(挂在 `documentElement` 上,z-index 最大),
每 2 秒轮询服务是否恢复,恢复后自动刷新页面。
- 不依赖 `window.confirm`(在嵌入/沙箱 WebView 里会被静默禁用)。
---
## 目录结构
```
dsh-web-restart/
├── package.json # dsh 插件清单(host bundle + client inject)
├── index.mjs # host 插件:/api/_dsh/restart 端点 + /restart 命令
├── cordis.patch.yml # 把 host 插件插入 profile 补丁树
├── lib/client.js # client 插件:侧边栏「重启 DSH」按钮 + 遮罩
├── launcher/macos/
│ ├── dsh-web-start.sh # 自动探测 node/dsh 路径的启动脚本
│ ├── com.dsh.web.plist # launchd LaunchAgent(占位符,安装时替换)
│ ├── dsh-web-control.sh # install/start/stop/restart/status/uninstall
│ ├── takeover.sh # 从手动运行平稳迁移到 launchd
│ └── DSH-Web-Launcher.applescript # 启动台图标 App 的源码
├── validate.mjs # host 插件逻辑自测(node validate.mjs)
└── README.md
```
---
## 开发 & 自测
```sh
node --check index.mjs lib/client.js # 语法检查
node validate.mjs # host 逻辑自测(桩 ctx,不启动服务)
```
---
## License
[MIT](LICENSE)
Install
dsh plugin --profile web add github:QIN-SMART/dsh-web-restart
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-web-restart from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.