前言¶
DSH 的理念是「一切皆插件」。實際寫過插件的人大多會遇到三類問題:從零起一個新插件時,規範散落在會話裏,每次都靠口述;裝了一個別人寫的插件,想知道它註冊了哪些槽位、路由和 UI 結構,只能整文件讀,token 燒得很快;想把某個插件的寫法搬過來或改成自己的版本,沒有明確的改造路徑,改完也不知道有沒有破壞原行爲。
wodaimnd/dsh-plugin-forge-preset 針對的就是這三件事。它是維護者 wodaimnd 寫的一個 DSH agent 預設(不是普通插件),裝上後模式下拉里多出一項「插件工坊」,會話裏可以直接說「幫我寫個插件」,也可以說「看看這個插件怎麼實現的」「把這個插件改成我要的樣子」。它的定位是把插件開發的規範固化在文件裏,而不是活在一次會話裏。
它是什麼¶
一句話:一個預設容器。presets/ 下每個子目錄是一個模式,plugin-forge 是正式的「插件工坊」,demo-mini 是架構驗證用的演示模式(可刪)。包版本 1.0.0,MIT 許可,作者 Kewei Chen。社區目錄裏的分類爲「客戶端」,星標數爲 0。
它和逆向模式(reverse)的區別值得先說清楚。兩者都做「拆開別人的東西」,但對象不同:
- 逆向模式拆 APK / IPA / PE / SO / 協議,產出是算法還原、脫殼產物;
- 插件工坊拆的是 DSH 插件的 JS bundle,拆的是槽位註冊、路由、工具行、UI 結構,產出是能安裝的新插件。
插件源碼本來就是可讀的 JS,所以 jadx / Frida / IDA 這套工具鏈在這裏用不上。
四個執行角色¶
插件內部有四個角色,併發上限 3 個,都是葉子節點(maxDepth: 1),不會無限往下派任務:
| 角色 | 幹什麼 | 觸發時機 |
|---|---|---|
| 插件測繪 | 出結構地圖、契約表、「能改/慎改/別碰」三分 | 要讀懂一個插件時 |
| 代碼吸收 | 判斷哪塊值得吸、遷入並驗證行爲不變 | 要借別人寫法時 |
| 改造分叉 | 選路線(原地改 / 複製分叉 / 補丁層)、七處替換、雙驗證 | 要改一個插件時 |
| 迴歸驗證 | 樁環境結構驗證 + 與原版差異對比 | 每次改造後 |
技能清單¶
說明一下:README 的小節標題寫的是「六個技能」,但下面的表格實際列了 7 項,按表格爲準。
| 技能 | 作用 | 關鍵產出 |
|---|---|---|
plugin-author |
從零寫插件:對齊 → 代碼 → 16 項自檢 | 完整可安裝插件 + 規範全文 |
preset-scaffold |
加新 agent 預設:建目錄 → 寫兩件套 → 驗證 | 新模式的完整模板與約束 |
plugin-search |
代碼定位:大綱 → 結構化搜索 → 定向讀取 | 精確行號,不整文件讀 |
plugin-index |
跨文件盤點:符號 / 引用 / 槽位 / 路由 | SQL 級查詢,替代重複掃描 |
plugin-recon |
摸清別人的插件 | 結構地圖 + 契約表 + 三分清單 |
plugin-harvest |
吸收可用代碼 | 吸收清單 + 遷入代碼 + 驗證腳本 |
plugin-fork |
改造成自己的版本 | 改造方案 + 分叉產物 + 雙驗證 |
技能裝在 $DSH_HOME/plugin-forge/skills/,由插件啓動時從包內同步。所有預設共享這一個技能庫,所以給插件工坊加的技能,新預設自動可用。
檢索工具與 token 預算¶
這是插件裏最實用的部分。四個工具按問題類型選:單文件降維用大綱器,跨文件查庫用索引庫,按語法結構找用 ast-grep,找字面量用宿主 grep。
下面是資料裏給出的實測數據:
| tokens / 耗時 | |
|---|---|
| 全文讀 6 個真實插件文件 | 95,064 tokens |
| 只讀結構大綱 | 1,470 tokens(省 98.5%) |
| 單文件最極端(222KB) | 全文 60,876 → 大綱 835 tokens |
| 建全庫索引(126 文件 / 1.5MB) | 456ms |
| 索引庫單次查詢 | 0.05ms |
用法如下,第一步是單文件或單插件的大綱:
# ① 單文件或單插件:先出大綱(讀大文件之前必做)
node tools/outline.mjs '<插件目錄>' --tokens
第二步是跨文件問題,建一次索引,之後都走查詢:
node tools/index.mjs build 'G:\AI PGRM\DSH\plugins'
node tools/index.mjs find PanelPage # 全庫幾處定義
node tools/index.mjs refs handleOperation # 誰引用了它
node tools/index.mjs slots # 哪些插件註冊了什麼槽位
node tools/index.mjs routes # 全部路由
node tools/index.mjs effects network # 所有網絡請求點
node tools/index.mjs stats # 庫規模 + 同名多定義
第三步是結構化搜索,README 強調規則:ast-grep 的 pattern 必須帶 $OBJ. 前綴,否則會漏掉 ctx.slots.register(...) 這種最常見寫法:
ast-grep run -p '$OBJ.slots.register({ name: $NAME, $$$REST }, $COMP)' -l js '<目錄>'
ast-grep run -p '$OBJ.webServer.register({ $$$REST })' -l js '<目錄>'
拿到行號後再定向讀,而不是整文件讀。硬規則也寫在 README 裏:讀任何大於 20KB 的文件之前,必須先跑 outline。
ast-grep 需要自行安裝,它 55MB,不在本包內,期望版本 0.51.1 或更高。不在 PATH 時插件會自動降級爲「大綱器 + 宿主 grep」,功能可用但結構匹配精度下降。另外 sg.exe 是棄用別名,不要用。
索引庫有三個已知邊界:引用是「調用點 + 大寫參數」而非全量標識符,小寫變量名作參數傳遞時查不到,這時改用 ast-grep;動態路由標註爲 (動態: route),不做猜測;增量更新依賴 mtime,改文件但 mtime 沒變會滯後,刪庫重建即可。
提示詞固化在哪¶
這是插件存在的核心目的:規範不能只活在會話裏。提示詞的分佈如下:
| 位置 | 內容 | 大小 |
|---|---|---|
presets/plugin-forge/persona.md |
人設與判斷規則(唯一真源) | 19KB |
presets/plugin-forge/agent.cordis.yml |
條目列表,人設位置用 %%PERSONA%% |
8.6KB |
skills/plugin-author/SKILL.md |
執行骨架:三步流程、判據表、輸出格式 | 4.2KB(渲染 4261/8192) |
skills/plugin-author/references/ |
runtime-contract / skeletons / ux / data-and-ownership / gates / failure-modes / prohibitions | 合計約 57KB |
docs/prompt-v2.1.md |
完整規範原文(含逐條理由與變更史) | 70KB |
拆成 SKILL.md + references 的原因很實際:宿主對 SKILL.md 有 8192 字符硬上限,超了會被修剪器裁掉後半段。SKILL.md 只放骨架與導航,長文按需讀 references/,不計入預算。
改人設的正確方式是改源文件再加校驗:
# 1. 改 presets/plugin-forge/persona.md(唯一真源)
# 2. 校驗(不寫盤)
python build-composition.py --check
# 3. 重啓 dsh
agent.cordis.yml 裏只有一行 %%PERSONA%%,落地時自動注入全文。不要直接改 .agent-presets/plugin-forge/agent.cordis.yml 這份落地副本,下次啓動會被源覆蓋。
安裝¶
包以 @local/dsh-plugin-forge-preset 的名字通過 link: 依賴裝進 profile,README 給的是 PowerShell 步驟,不是 dsh plugin add:
# 1) 包目錄放到任意位置,然後加進 profile 依賴
$profile = $env:DSH_PROFILE_DIR
$pkg = Get-Content -Raw -Encoding UTF8 "$profile\package.json" | ConvertFrom-Json
$pkg.dependencies | Add-Member -NotePropertyName '@local/dsh-plugin-forge-preset' `
-NotePropertyValue 'link:<包目錄絕對路徑>' -Force
$pkg.dsh.profile.bundles += '@local/dsh-plugin-forge-preset'
$pkg | ConvertTo-Json -Depth 12 | Set-Content "$profile\package.json" -Encoding UTF8
# 2) 建 junction,讓 Loader 能按包名解析
New-Item -ItemType Junction -Path "$profile\node_modules\@local\dsh-plugin-forge-preset" `
-Target '<包目錄絕對路徑>'
重啓 DSH 後,模式下拉里就會出現「插件工坊」。
運行時行爲與排障¶
啓動時插件依次做四件事:把 preset.yml + agent.cordis.yml 落到 $DSH_HOME/.agent-presets/plugin-forge/;把 skills/ 同步到 $DSH_HOME/plugin-forge/skills/;等 agentPresets 服務就緒(最長 20 秒),然後調 ctx.agentPresets.register() 聲明進下拉;把結果寫進 $DSH_HOME/plugin-forge/preset-declare.json。
第三步是必須的。Web 的模式下拉只認 register(),只把目錄寫到 .agent-presets 不會被掃到,README 把這稱爲「插件裝得完整、下拉里卻沒有它」的唯一根因。
裝完直接看 preset-declare.json 判斷結果:
{
"ok": true,
"phase": "registered",
"id": "plugin-forge",
"name": "插件工坊",
"plugins": 19,
"broken": null,
"skillsDir": "...",
"presetDir": "..."
}
phase 的含義如下:
| phase | 含義 | 怎麼辦 |
|---|---|---|
registered |
正常 | 無 |
registered-broken |
已聲明但掛載失敗 | 看 broken 字段 |
waiting-registry |
等 agentPresets 服務 |
通常幾秒內自動過去 |
registry-timeout |
20 秒沒等到服務 | 檢查 @deepseek-ai/dsh-agent-preset-registry 是否在 profile 裏 |
install-failed |
預設文件落地失敗 | 看 error,檢查 $DSH_HOME 寫權限 |
配置項表中,README 明確給出的只有 syncSkills(默認 true,控制是否把本包技能同步到 $DSH_HOME/plugin-forge/skills)。其餘配置項資料裏沒有出現,這裏不列。
包內還聲明瞭 dsh.forge.effects:fs:read 任意絕對路徑(測繪別人的插件)、fs:write 到 $DSH_HOME/.agent-presets/plugin-forge(落地預設)、fs:write 到 $DSH_HOME/plugin-forge(技能同步與狀態文件)、http:loopback:/api/dsh-plugin-forge-preset(設置頁數據路由)。
繼續加新預設¶
加一個新預設不需要改任何 JS:
- 在
presets/下建目錄,目錄名 = preset id,需匹配^[a-z0-9][a-z0-9-]{0,31}$ - 寫
preset.yml:name/description/order(前兩個必須單行,order 必須數字) - 寫
agent.cordis.yml:條目列表,至少含 persona、skill-filesystem、一個 shell 工具 - 人設長時用
%%PERSONA%%佔位符 + 同目錄persona.md - 重啓 dsh
停用有兩檔:放空文件 presets/<id>/.preset-off,或者把目錄改名加下劃線(如 _<id>),結果都是不落地、不註冊、副本保留。徹底移除就是刪掉整個預設目錄,下次啓動會自動清掉 .agent-presets/<id>。
中文優先¶
插件約定 UI 文案、按鈕、錯誤提示一律簡體中文,插件展示名與描述一律簡體中文,默認不做多語言——不創建 en.json,不留雙語字典,不寫 locale 切換,只有用戶明確要求時才做雙語。package.json 裏雖然有 ./locale/*.json 的 exports 字段,但按 README 的約定,默認不帶多語言資源。
適用場景與注意¶
適合兩類人。一類是本來就要在 DSH 上寫插件的人:需要按規範從零起插件、跑 16 項自檢,省掉重複詢問。另一類是想讀懂或改造別人插件的人:用測繪 / 吸收 / 分叉三檔流程,配合省 token 的檢索工具,避免整文件讀。
使用時有幾點要留意:
- 插件以當前 dsh 進程的權限運行,資料裏聲明的
fs:read是任意絕對路徑,安裝前應先檢查源碼與許可證。 - 定製人設或規範時改
presets/下的源文件,不要改.agent-presets/裏的落地副本。 - 想用滿檢索能力需要自行安裝 ast-grep(0.51.1 及以上),不裝也能降級運行。
- 索引庫的引用關係不是全量標識符,跨文件結論拿不準時用 ast-grep 複覈。
結尾¶
這個插件的價值不在於多了一個模式,而在於把插件開發的規範從會話裏搬到了文件裏,並配了大綱器、索引庫和結構搜索來把 token 成本壓到可承受的水平。如果要裝,先看目錄頁和倉庫裏的 README,源碼與許可證確認無誤後再放進 profile。
- 社區目錄頁:https://www.skillhub.cn/plugins/wodaimnd/dsh-plugin-forge-preset
- GitHub:https://github.com/wodaimnd/dsh-plugin-forge-preset