dsh-restart-button:DSH 桌面版側邊欄一鍵熱重載與兜底重啓

前言

在 DeepSeek Harness(DSH)桌面版裏開發或維護插件時,常見流程是改代碼、裝新包或 git pull 更新 bundle,然後關掉應用再打開,才能確認改動生效。完全重啓會清掉正在跑的輪次、子代理、終端會話、排隊消息和未發送草稿——成本比「刷新一下界面」高得多。

Harness 宿主側其實有 HMR:在進程仍存活的前提下驅逐已變更模塊並重新加載。缺的是一條從 UI 觸達這條路徑的入口,以及在 HMR 無法完成時再走完全重啓的明確分支。下面介紹社區插件 accoutmissing/dsh-restart-button 如何把這個流程收成側邊欄底部的一個按鈕。

這是什麼

dsh-restart-button 由維護者 accoutmissing 發佈,分類爲客戶端插件(Cordis bundle,當前 package 版本 0.3.0,MIT 許可證)。它在 DSH 桌面版側邊欄底部提供重載 / 重啓按鈕:默認嘗試原地熱重載已變更的插件代碼;僅當宿主報告熱重載無法完成時,按鈕才切換爲完全重啓,再點一次纔會殺掉應用並重新拉起。

社區目錄頁:skillhub.cn/plugins/accoutmissing/dsh-restart-button。源碼與說明:github.com/accoutmissing/dsh-restart-button。目錄站點爲社區生態索引,與 DeepSeek / 幻方無官方從屬關係。

爲什麼優先熱重載

README 中的設計取捨很直接:app.relaunch() 並不便宜。插件包替換後,Harness 的 HMR 層可以在運行中的宿主進程內驅逐變更模塊並重新啓動,會話與進行中的任務仍留在同一進程裏。完全重啓是兜底——例如 hmr.reconcileProfile() 返回 restartReason: 'module-comparison' 或 'package-moved' 時,模塊無法就地 reconcile 或包在磁盤上移動了位置。

按鈕默認走熱重載;只有 Harness 明確需要重啓時,才暴露「完全重啓」路徑。

點擊  ->  原地熱重載插件
           |
           +-- 熱重載不成立  ->  按鈕變成「完全重啓」
                                  再點一次 -> 應用重新拉起

核心功能

側邊欄按鈕與狀態

客戶端掛在 sidebar.footer.action(order 90),狀態機大致如下(文案以 README 表格爲準):

按鈕顯示 含義 點擊會發生什麼
⟳ 刷新插件 空閒 原地熱重載已變更的插件代碼
⟳ 正在刷新… 進行中 —
✓ 已刷新 完成 3 秒後回到空閒
⟳ 完全重啓 熱重載無法原地完成 殺掉應用並重新拉起
⚠ 刷新失敗 出錯(同時寫日誌) 3 秒後回到空閒

安裝 bundle 成功後按鈕即出現;README 寫明安裝本身不需要重啓。

宿主 HTTP 路由

宿主在 index.js 通過 webServer 註冊三條路由:

路由 方法 用途
/plugins/dsh-restart-button/__state GET 版本、代號、能力、pid 等自描述
/plugins/dsh-restart-button/__reload POST hmr.runExclusive(() => hmr.reconcileProfile())
/plugins/dsh-restart-button/__restart POST 完整 kill 後重新拉起

熱重載在 hmr.runExclusive() 內執行,避免與自動重載併發時出現 transactions cannot be nested;該錯誤會識別並退避重試(3 次,400 ms × n),另有 20 秒超時上限。

安全與調試

兩條 POST 路由要求請求頭 x-dsh-restart-button,並校驗 loopback 來源。對寫路由發 GET 返回 405。

日誌:~/.dsh/restart-button.log(約 1 MB 輪轉)。Windows 下重啓腳本與臨時目錄在 %TEMP%\dsh-restart\<timestamp>\;重啓路由支持 ?dry=1(只生成腳本)與 ?probe=1(替身 helper 跑鏈路、不真殺進程)。

平臺說明: 完全重啓的啓動鏈路在 README 中僅針對 Windows 實現並驗證;熱重載依賴有文檔的宿主 HMR 服務,不限於 Windows,但作者註明尚未在其他平臺實測完全重啓。

安裝與啓用

這是一個 Cordis bundle。官方 README 給出的步驟是先檢出源碼,再對目錄執行 install_bundle(Harness 插件管理器能力;由 agent 驅動時爲 plugin_manager 工具)。

先從源碼檢出:

git clone https://github.com/accoutmissing/dsh-restart-button.git

然後用本地目錄安裝 bundle(將 target 換成你機器上的實際路徑):

{ "action": "install_bundle", "target": "D:/path/to/dsh-restart-button" }

安裝成功應返回 application: "applied"。以後更新:在倉庫目錄 git pull,再點側邊欄按鈕觸發熱重載即可。

注意: 插件與當前 DSH 進程同權限運行。安裝前請自行閱讀倉庫源碼與 MIT 許可證,確認行爲與安全約束(請求頭、loopback)符合你的環境。

典型用法

  1. 安裝 bundle 後,在側邊欄底部找到刷新按鈕。
  2. 修改或更新插件代碼後,在空閒態點擊 刷新插件,等待熱重載完成(成功時短暫顯示 已刷新)。
  3. 若按鈕變爲 完全重啓,說明宿主判定必須重啓;再點一次執行完全重啓(Windows 上經文檔描述的 launch 鏈路)。
  4. 排查問題時查看 ~/.dsh/restart-button.log;在 Windows 上還可查看 %TEMP%\dsh-restart\ 下保留的最近 20 次 launch.log / 腳本產物。

實現要點(讀者可選)

客戶端狀態放在模塊級 store 而非組件 useState:sidebar.footer.action 在 store 更新時會重掛載組件,組件內 state 會在兩次點擊間被重置。判斷新客戶端是否加載時,宿主返回 clientStamp(client.js 的 mtime),頁面記錄 LOADED_AT;若 clientStamp 比加載時刻新超過約 1 秒,則整頁重載——README 說明早期用 clientModules.graph().rev 會誤判,已改爲文件戳。

與 dsh-unlag 對照:本插件借鑑了 nested transaction 重試、超時與日誌消毒、自定義請求頭 CSRF、熱重載優先等思路;未採用其 /plugins 路由 shim,而選擇在需要時用整頁重載。完全重啓、Windows Job Object 逃逸、wscript 快捷方式啓動鏈等爲獨立實現,README 有完整鏈路說明。

結尾

dsh-restart-button 把「裝插件 / 更插件就要關應用」收成側邊欄一步:能熱重載就不重啓,不能時才完全拉起。適合長期在 DSH 桌面版裏迭代 Cordis 插件、又不想頻繁丟會話的開發者。

  • 目錄頁:https://www.skillhub.cn/plugins/accoutmissing/dsh-restart-button
  • GitHub:https://github.com/accoutmissing/dsh-restart-button
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜