Skip to content
dsh.fish
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

  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source