dsh-pluginlet:把工作區裏的 .pluginlet 變成獨立沙箱對話標籤頁

前言

在 DeepSeek Harness(DSH)裏做倉庫內的輕量 UI,常見做法是單獨寫前端、再掛進宿主,或把邏輯塞進一個大插件裏。倉庫裏如果有多份小腳本、小面板,往往難以在對話視圖裏「一文件一標籤」呈現,也難在改動後仍可控地授權讀、寫和網絡。

下面介紹維護者 AlseFum 的 dsh-pluginlet(GitHub:AlseFum/dsh-pluginlet,社區分類 admin-security)。它把工作區中符合規則的每個 *.pluginlet 文件變成 Conversation View 裏的獨立標籤頁;運行前按內容哈希綁定能力授權,寫入只能通過宿主確認完成。當前 README 標明 experimental, source-only,尚未發佈到 npm,需從倉庫 Git URL 安裝。

這是什麼

dsh-pluginlet 是 DSH 的 Web 側插件:掃描工作區內指定目錄下的 *.pluginlet 純 JavaScript 文件,每個文件對應一個標籤(例如 對話 / 軌跡 / hello)。插件隨倉庫攜帶的 pluginlet 會隨檢出一起可用,不依賴按項目再裝 npm 包。

設置不在插件 UI 裏改,而在宿主插件配置(Plugins → Pluginlet,或該 bundle 對應行的 config:)中完成。

核心功能

發現與標籤

默認只掃描工作區根下的 .dsh/pluginlets/(根目錄散落的 *.pluginlet 不會變成標籤)。可通過 directories 增加搜索路徑;extensions 默認 ['.pluginlet']。

示例佈局:

repo/
  .dsh/pluginlets/
    app.pluginlet       ->  標籤名 "app"
    schema.pluginlet    ->  標籤名 "schema"
    hello.pluginlet     ->  標籤名 "hello"

發現上限由 maxEditors(默認 64)與單文件 maxEditorBytes(默認 524288)約束。

pluginlet 編寫約定

.pluginlet 爲純 JavaScript:無 JSX、無 import(安裝無構建步驟)。可導出三種形態之一:

  1. 默認導出函數(迷你 React:api.h + hooks)
  2. setup(api) 返回渲染函數(類 Vue)
  3. mount(el, api) 命令式掛載

api 提供 h、Fragment、常見 hooks、fs.read / fs.list(包裝讀)、net.fetch(包裝網絡)、write.request(僅發起確認,不自行寫盤)、ui.toast、meta.name / meta.path 等。安裝 Host 半部後會註冊技能 pluginlet-development,正文在 skills/pluginlet-development.md,供智能體寫 pluginlet 前加載。

安全與授權

掃描器是策略門,真正邊界是沙箱:pluginlet 在 sandbox="allow-scripts" 的 iframe 中運行,CSP 極嚴;fs / net 僅通過 postMessage 到宿主,再訪問 /api/pluginlet/*,並記入審計。

  • 寫入無宿主確認對話框則不可能;幀內只有 write.request。
  • eval、import/require、裸 fetch 等由掃描阻斷,不可授予。
  • 授權按內容哈希與路徑作用域綁定,批准數據存放在 $DSH_HOME/pluginlet/,不進倉庫。
  • 批准發生在該 pluginlet 標籤要運行時;對話框可按能力勾選路徑子集。
  • devMode: true 時(工作區可見橫幅)可接受哈希變更而免重新批准,並放寬可授予能力,被阻斷的構造仍被阻斷。

主要配置項(節選):

key 默認值 含義
devMode false 變更哈希可不重新批准(仍審計;讀寫網絡仍受控)
extensions ['.pluginlet'] 視爲 pluginlet 的後綴
directories ['.dsh/pluginlets'] 相對工作區根的搜索目錄
allowRead / allowNetwork / allowWrite true 是否允許提供對應能力
net { perMinute: 20, perHour: 240, maxBytes: 1048576 } 每個 pluginlet 的網絡預算

宿主 API

路由均爲 POST,路徑前綴 /api/pluginlet/,並要求請求頭 x-dsh-plugin: pluginlet。包括 discover、scan、source、state / grant / revoke / log、fs/list、fs/read、net/fetch、write 等(網絡僅限 http(s)、有超時與大小與速率限制)。

安裝與啓用

在 profile web 下添加插件(README 原文命令):

dsh plugin --profile web add github:AlseFum/dsh-pluginlet

也可使用完整 Git URL:https://github.com/AlseFum/dsh-pluginlet.git。克隆爲完整包,無需 npm install 或構建。

配置示例(cordis.patch.yml 片段):

- id: pluginlet
  config:
    devMode: false
    allowNetwork: false

或在 Plugins 頁面安裝爲 Pluginlet。修改 Host 半部後需重啓 dsh web;客戶端半部刷新頁面生效。

package.json 中版本爲 0.1.0,許可證 MIT,要求 Node >= 22.0.0。GitHub 星標數以目錄站展示爲準(抓取時爲 0)。

典型用法

  1. 在工作區創建 .dsh/pluginlets/,新增 hello.pluginlet。
  2. 重啓或刷新 DSH Web,在 Conversation View 看到對應標籤。
  3. 首次運行時在標籤內完成能力批准(按需縮小路徑作用域)。
  4. 需要寫文件時,在代碼裏調用 write.request(target, text, version),在宿主對話框確認。

最小計數器示例(README 摘錄):

export default function Editor(api) {
  const [count, setCount] = api.useState(0)
  return api.h('div', { style: { padding: '12px' } },
    api.h('button', { onClick: () => setCount(count + 1) }, '+1'),
    ' ' + count)
}

適用場景與注意

適合:需要在同一倉庫內維護多個小型、可審查的沙箱 UI(配置預覽、Schema 編輯、運維小面板等),且希望授權與源碼哈希、路徑作用域強綁定。admin-security 分類與此一致:強調宿主側策略、審計與確認寫。

注意:

  • 插件以當前 DSH 進程權限運行;安裝前請閱讀源碼與 MIT 許可證,並理解 devMode 與 allowNetwork 等開關的含義。
  • 網絡代理對 DNS 重綁定等仍有殘餘風險,README 明確其爲護欄而非完整出站過濾。
  • DSH 社區插件目錄(如 SkillHub 上的條目)爲獨立生態站點,與 DeepSeek / 幻方無官方從屬關係;非 npm 正式發佈階段,升級與變更以 GitHub 倉庫爲準。

結尾

dsh-pluginlet 把「一文件一標籤」和哈希綁定的能力授權結合起來,讓倉庫自帶的 .pluginlet 能在對話視圖裏安全試運行。進一步細節見倉庫 README 與 docs/DESIGN.md。

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

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

小夜