前言¶
DSH 的設計是「一切皆插件」,Host 升級、配置改動、服務異常之後,都需要重啓 Host 讓改動生效。常規做法是打開終端手動結束進程再拉起來,Web 界面上沒有任何入口,跑着的回合和終端也會被中斷,因此很難在瀏覽器裏完成一次靠譜的重啓。
下面介紹的 dsh-restart 就是爲了把這個動作放進 Web GUI:在 Settings → General 里加一行,在側邊欄賬號菜單里加一項,同時也暴露一個 agent 工具 dsh_restart。插件由 dengnianchen 維護,託管在 GitHub,屬於客戶端分類,主站目錄頁有收錄。
這是什麼¶
一句話:給 DeepSeek Harness 的 Web 界面加一個 Host 重啓入口,並且在沒有 systemd 時也能工作。
它解決的問題是:
- Web GUI 上無法觸發 Host 重啓,改完配置只能靠終端。
- 在進程內直接調用
systemctl restart會連自己一起殺掉(下面的實現部分解釋原因)。 - 重啓後的頁面刷新需要可靠判斷,不能把一次短暫斷連當成成功。
插件是普通的 bundle plugin,包含 Host 半部分和 Web 半部分(一個 ESM 模塊加一段客戶端代碼),不改動側邊欄 footer 圖標、Host 文件和 profile 裏手寫的配置。
核心功能¶
三個入口,做的是同一件事:
| 入口 | 位置 | 實現方式 |
|---|---|---|
| 設置行 | Settings → General,排在 “Performance & usage” 之後 | 官方 settings.general.item 插槽,order: 35,行外殼沿用 Host 自己的 General 行樣式 |
| 賬號菜單項 | Settings / Feedback / Restart dsh / Sign out 之間 | DOM 橋接,原因見下面的限制說明 |
| Agent 工具 | dsh_restart({ delayMs? }) |
與上面兩個 UI 入口走同一套重啓邏輯 |
重啓動作的交互流程:
- 第一次點擊進入警告態,提示
Click again to confirm,4.5 秒後自動失效。 - 第二次點擊排定重啓,界面顯示
Restarting…。 - 頁面每 0.7 秒輪詢
/dsh-restart/status,只有當 Host 返回的 pid 與之前不同時才重新加載頁面——這樣重啓過程中的短暫斷連不會被誤判爲成功。 - 如果 120 秒內沒有出現新進程,控件轉爲錯誤態並提供重試。
重啓過程中,正在運行的回合和終端會被中斷;會話、transcript 和設置都會保留。
安裝與啓用¶
安裝命令來自插件 README:
plugin_manager install_bundle @dyapple/dsh-restart
插件需要 DeepSeek Harness ≥ 0.2.1-rc.3,因爲它使用了 ctx.connection.requestRejection 和 settings.general.item 插槽。
重啓是怎麼發生的¶
Host 側按運行環境分兩條路徑,兩者都會先延時,保證 HTTP 響應在 Host 退出之前回到頁面。
- systemd 環境。插件通過
INVOCATION_ID和/proc/self/cgroup裏的普通.service判斷自己是否跑在 systemd 下,並確認systemd-run --user可用;此時會用一個 detached transient unit 延時執行systemctl --user restart <unit>。
這裏不能直接從進程內調用 systemctl restart:dsh-web 的 KillMode=control-group,重啓會先把執行調用的輔助進程一起殺掉。transient unit 跑在另一個 cgroup 裏,可以繞開這個問題。
- 非 systemd 環境(例如手工啓動的進程)。用一個 detached 的
/bin/sh等待舊 pid 消失、端口穩定,然後exec同一條命令行,同時舊進程退出。
HTTP 接口¶
插件註冊了兩個接口:
| 路徑 | 方法 | 用途 |
|---|---|---|
/dsh-restart/status |
GET | 返回 {ok, version, pid, mode, unit, command, startedAt, uptimeMs, restarting} |
/dsh-restart/restart |
POST | Body 爲 {delayMs?},默認 700 ms |
兩個接口都先經過 ctx.connection.requestRejection()(Connection 的 Host/Origin 限制加上簽名 Cookie);POST 還額外要求 content-type: application/json,跨站的簡單請求無法攜帶這個頭。沒有 Cookie 時兩個接口都返回 401。
賬號菜單項的限制¶
賬號菜單項是 DOM 橋接實現,不是官方插槽。原因是:@deepseek-ai/dsh-client-ui-settings-account 裏的菜單項是硬編碼數組,沒有爲額外行預留插槽;它唯一的位置 settings.launcher 是單值的,佔用它等於替換整個賬號菜單。
因此插件的做法是:監聽 [role="menu"] 節點,用同時包含 Settings 和 Feedback 標籤來定位賬號菜單,克隆隨包發佈的 Settings 行(繼承其 class、幾何與 hover 樣式),替換圖標和文案,再插到 Sign out / Sign in 之前。
具體限制:
- 它在 React 的菜單項列表之外,Tab 鍵可以到達,方向鍵不行。
- 它依賴隨包發佈的菜單文案和結構。如果後續版本改了文案,它會靜默消失——不報錯,也不影響其他 UI。設置行不受影響,因爲它用的是官方插槽。
- 每次菜單打開時節點會被重建,用
WeakSet防止重複插入。
適用場景與注意¶
- 適合:已經用 systemd user service 託管 DSH Host、並且主要通過 Web GUI 操作的人;想在 agent 裏通過工具觸發重啓的開發者。
- 不適合:需要重啓立刻完成的場景。即使使用默認延時,從點擊到 Host 恢復也會有數秒停頓,正在運行的回合和終端會被中斷。
使用時需要注意:
- 插件以當前 dsh 進程的權限運行,重啓動作因此繼承了啓動該進程的用戶權限。安裝前應先檢查源碼(倉庫公開在 GitHub)和許可證。本插件使用 MIT 許可證,版權人爲 Nianchen Deng。
- 賬號菜單項依賴客戶端 UI 的文案結構,升級客戶端後如果入口消失,可回退到 Settings → General 裏的那一行,或直接使用
dsh_restart工具。
開發調試¶
從源碼開發時按 README 的步驟:
git clone https://github.com/dengnianchen/dsh-restart.git
plugin_manager install_bundle ./dsh-restart
profile 會鏈接這份 checkout,因此 client.js 的改動通過 HMR 生效;index.js 的改動需要重啓 Host——恰好可以用這個插件自己來做。Host 半部分是一個單文件 ESM 模塊,每個進程只引入一次。
小結¶
dsh-restart 把 Host 重啓從終端搬進 Web GUI,用官方插槽保證設置行的可靠性,用 pid 變化判斷重啓是否真正完成,並在 systemd 和非 systemd 兩種環境下都給出可工作的實現。代價是賬號菜單項依賴客戶端 UI 的當前結構,升級客戶端後可能需要留意。
相關信息頁:
- 社區目錄頁:https://www.skillhub.cn/plugins/dengnianchen/dsh-restart
- 代碼倉庫:https://github.com/dengnianchen/dsh-restart