dsh-bundle-manager:DSH 第三方插件的運行時掛載管理器

前言

DeepSeek Harness(DSH)的理念是「一切皆插件」,但按官方鏈路,寫進 dsh.profile.bundles 的 bundle 會隨進程啓動加載、長期駐留。想臨時停用一個第三方插件,就得改 profile manifest、再重啓。同時 DSH 有一條關鍵架構要求:可選第三方插件只能放在 dependencies,不得寫入 dsh.profile.bundles——也就是說,官方靜態層並沒有給這類插件提供運行時啓停的位置。

dsh-bundle-manager 補的就是這一環:它經 Loader API 在進程內掛載/卸載 bundle 行,即時生效、無需重啓、不改寫 profile manifest,並提供命名預設與自愈式失敗回退。下面逐項介紹。

這是什麼

dsh-bundle-manager 由 KaramachiA217 維護,MIT 許可證,定位是 DeepSeek Harness 可選第三方插件包的運行時掛載管理器。安裝後它自己作爲框架 bundle 進入官方靜態層,並在設置頁提供「插件掛載管理」區塊;被管理的第三方插件則只放在 dependencies 裏,由它在運行時掛載。

兩條架構約束先交代清楚:

  1. 可選第三方插件只能放在 dependencies,不得寫入 dsh.profile.bundles
  2. 本插件是唯一在運行時掛載這些插件的框架 bundle。

核心功能

草稿開關與一次性應用

在設置頁的本地草稿中切換插件開關,點擊 Save & Refresh 一次性應用整張表:主機側 diff 出需要創建/移除的掛載並持久化,隨後硬刷新頁面,使客戶端半部對齊。apply 走串行隊列,單次上限 30 秒。

命名預設

可以把當前草稿組合保存爲命名預設:未提交的切換會合並進快照,保存新名稱的預設會自動激活。之後從下拉框切換預設即可;刪除支持多選,帶不可逆確認,並拒絕刪除 default 預設與當前活動預設。

自愈式失敗回退

壞插件不會拖垮其他插件:出錯的插件落入 Failed 分組(含 kind、嘗試次數、錯誤信息),其餘插件繼續工作。內置 20 秒掛載看門狗;啓動時按分組並行,組數由 DSH_PM_BOOT_GROUPS 控制,取值 1–8。

安全機制

framework 白名單保護核心 bundle(標記爲 framework-protected);註冊表原子寫入並保留 .bak 最近可用副本;支持自動舊路徑遷移。

與官方靜態層雙軌共存(v0.5)

v0.5 引入了官方靜態層(dsh.profile.bundles)與 bm 運行時層之間的可逆切換:

  • import-to-bm:把靜態層裏的插件導入 bm,交給運行時管理;
  • export-to-bundles / export-all-to-bundles:把 bm 管理的插件導出回官方靜態層,後者可作爲移除 bm 前的安全網批量導出全部。

被靜態層覆蓋的插件在 bm 中只讀顯示爲 superseded-by-static。導入/導出會編輯 profile manifest,是「永不改寫 manifest」規則的三個顯式例外,且全部走 A 級冗餘:原子寫入 + .bm.bak 備份 + JSON.parse 回滾、一鍵批量回滾、依賴組提示、框架硬保護。

注意:軌道切換(導入/導出)需要重啓;bm 運行時層自身的掛載/卸載是零重啓。

卸載半程(v0.5)

卸載分兩步:先由 bm 註銷註冊表行(只清 bm 自有文件,不動 manifest),再引導執行官方 dsh plugin remove pkg...(支持批量)。先清註冊表行是爲了保持可逆:若官方移除失敗,包降級爲休眠依賴(已安裝、空閒),可在設置頁重新開啓(重寫註冊表行)恢復管理。另有響應式 GC,清理繞過 bm 被外部移除的包的註冊表行,並記錄一條可見的 failed 條目。

圍欄 API

上述能力經圍欄 API /bundle-manager/api(browser-trust fence)暴露,共十個接口:listapplypreset/savepreset/switchpreset/deleteimport-to-bmexport-to-bundlesexport-all-to-bundlesimport/rollbackuninstall

安裝與啓用

用官方 CLI 安裝,一步完成依賴添加,隨後 reconcile 會把包追加到 dsh.profile.bundles

dsh plugin --profile <profile-name> add dsh-bundle-manager

安裝後 CLI 生成的 profile 佈局形如:

{
  "dependencies": { "dsh-bundle-manager": "^0.5.3" },
  "dsh": { "profile": { "bundles": ["dsh-base", "dsh-web-app", "dsh-settings-ui", "dsh-bundle-manager"] } }
}

升級時重新運行並加 @latest

dsh plugin --profile <profile-name> add dsh-bundle-manager@latest

運行環境要求 Node >= 20;peerDependencies 包含 dsh-settings-ui >=0.3.0@deepseek-ai/cordis >=4.0.0-rc.0@deepseek-ai/dsh-host-webserver >=0.1.0-rc.0@deepseek-ai/dsh-client-runtime >=0.1.0-rc.0@deepseek-ai/dsh-client-ui-slots >=0.1.0-rc.0

本地開發與測試

本地開發時,先用 npm pack 構建 tarball,再用官方 CLI 安裝本地包(或 file: 依賴),每次改動需重新打包:

npm pack
dsh plugin --profile <profile-name> add ./dsh-bundle-manager-<ver>.tgz

已知差異:在 rc.6 上 link: 掛載會因 ESM 解析失敗,請改用 file: tarball。

測試與 CI 各有一條命令:

npm test     # 離線迴歸,210 斷言,mock ctx 驅動圍欄 API
npm run ci   # 5 步門禁:語法 + 測試 + 密鑰掃描 + 淨化 + 打包白名單

兼容性

  • dsh 0.1.0-rc.5:已在官方桌面 shell(僅框架 bundle)驗證。
  • rc.6(2026-08-17 驗證):與 rc.5 同上遊提交 47f9438,運行時掛載/卸載、framework 白名單、失敗隔離、預設、註冊表持久化與客戶端半部均零代碼適配通過。
  • rc.7(2026-08-19 驗證):bm 唯一使用的 kit 面 settings.section 在 rc.7 上不變;kit 鎖定 npm 發佈版 dsh-settings-ui@0.2.22,不依賴 kit 0.3.0 的 pluginCard/settingsScope

完整中文手冊見倉庫的 MANUAL.md。

適用場景與注意事項

適合的用戶:

  • 需要頻繁啓停第三方插件、不想每次改 manifest 再重啓的 DSH 用戶;
  • 想把不同插件組合保存爲預設、按任務一鍵切換的用戶;
  • 想先在 bm 運行時層試用靜態層插件、再決定是否固化(或反向導出)的用戶。

使用前注意:

  1. 軌道切換(import-to-bm / export-to-bundles / export-all-to-bundles)需要重啓,且是「永不改寫 manifest」的僅有的三個例外;bm 運行時層的掛載/卸載零重啓。
  2. apply 爲串行隊列、30 秒上限;預設刪除是不可逆操作,default 與當前活動預設受保護。
  3. 家族單軌說明:其他第一方家族插件(mcp / search / proxy / skill / balance 等)保持 dependencies-only 單軌,由 bm 在運行時掛載,不參與導入/導出;雙軌是面向外部用戶的可選增強。
  4. 插件以當前 dsh 進程權限運行,安裝前應檢查源碼與許可證。

小結

dsh-bundle-manager 把第三方插件的啓停從「改 manifest + 重啓」變成設置頁裏的一次點擊,失敗隔離與雙軌共存讓試錯成本可控。如果你的 DSH profile 裏插件較多,值得一試。

  • 社區目錄頁(獨立站點,與 DeepSeek / 幻方無官方從屬關係):https://www.skillhub.cn/plugins/KaramachiA217/dsh-bundle-manager
  • GitHub 倉庫:https://github.com/KaramachiA217/dsh-bundle-manager
羽毛球分组比赛记分
小程序二维码

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

小夜