前言¶
用 DSH Web 做日常開發時,有兩類報錯比較容易碰到。一類是 session 權限已經切到 danger-full-access 之後,模型重試仍然攜帶 sandbox_permissions 和 justification 字段,DSH 在真正執行前拒絕請求,報 not strictly wider;另一類出現在 WSL 環境,在 DSH Web 裏點擊文件路徑時報 spawn powershell.exe ENOENT,文件打不開。
DSH 的理念是一切皆插件,這類兼容性修復適合做成 out-of-tree 插件。下面介紹 MarvekG 維護的 @MarvekG/dsh-plugins,它針對這兩個問題各提供一個獨立入口。
這是什麼¶
@MarvekG/dsh-plugins 是一組 out-of-tree 的 DSH 插件集合,定位是兼容性修復與增強。MIT 許可證開源,當前版本 0.1.0,運行時依賴 highlight.js ^11.12.0。
包內目前有兩個入口:
@MarvekG/dsh-plugins/sandbox-same-mode
@MarvekG/dsh-plugins/path-viewer
入口由 cordis.patch.yml 單獨掛載,每個入口擁有自己的 Cordis 生命週期,可以單獨加載和卸載。以後新增修復時,只需新增一個腳本、一個 exports 子路徑和一個獨立的 patch 行。
另外要注意包名:這個包從 @MarvekG/dsh-bug-fix 更名而來。如果裝過舊包,升級不能走「更新」流程,具體見後面的安裝一節。
核心功能¶
sandbox-same-mode:處理冗餘沙箱升級字段¶
先看報錯本身。session 權限已經切換爲 danger-full-access 後,模型重試仍可能攜帶這樣的參數:
{
"file_path": "/home/wang/codes/StickyProxy/plugin/internal/state/store.go",
"content": "x",
"sandbox_permissions": "workspace-write",
"justification": "write the requested plugin fix outside the workspace"
}
DSH 在寫入真正執行前報錯:
sandbox escalation to "workspace-write" is not strictly wider than this call's current "danger-full-access" mode
原因在於:有效權限按 session 決定,而工具 schema 會公開所有可能的升級目標。模型可能在較窄權限下收到重試指引,之後 session 切換到相同或更寬權限,它仍繼續使用該參數。例子裏 workspace-write 比當前的 danger-full-access 更窄,請求字段並沒有增加能力,DSH 因此把它正確地拒絕爲非升級請求。
插件的做法是在工具註冊時包裝其執行函數,因此同時覆蓋普通全局工具和 DSH Web 的 preset-scoped bash、pwsh、write、edit 工具。只有以下條件同時滿足時,它才刪除升級字段並按當前權限執行:
sandbox_permissions是該工具 schema 明確公開的枚舉值;justification是非空字符串;- 請求權限不寬於當前調用、當前 session 的有效 sandbox 權限。
此時請求只是冗餘聲明,不彈審批,也不再報 not strictly wider。
真正的權限升級和非法輸入仍走原流程:
read-only→ 更高權限:繼續申請審批;workspace-write→danger-full-access:繼續申請審批;- 缺少說明、說明爲空或參數不完整:繼續報錯;
- 未被工具 schema 公開的權限值(包括僞造的同級值):仍由 DSH 原始參數校驗拒絕。
這個入口不擴大工作區、不修改 workspaceRoot、不偷偷增加權限。有效權限仍爲 workspace-write 時,去掉冗餘升級字段後,工作區外的請求仍可能因爲沙箱工作區邊界被拒絕。
path-viewer:瀏覽器內查看文件與目錄¶
第二類報錯發生在 WSL 下點擊 DSH Web 裏的文件路徑時:
path open failed: path open failed: spawn powershell.exe ENOENT
WSL 下 DSH 通過 powershell.exe 把路徑交給 Windows 桌面打開。如果 /etc/wsl.conf 配置了 [interop] appendWindowsPath = false,Windows 目錄不會追加進 PATH,裸命令名 spawn 直接 ENOENT。而且「從 WSL 喚起 Windows 桌面」本就脆弱——GUI 本身就跑在 Windows 瀏覽器裏。
插件把原生打開換成純瀏覽器方案,全程不 spawn 任何 Windows 進程。具體分兩步:
- 在同一個 web 服務上註冊帶回環圍欄的
GET /view?path=<絕對路徑>[&line=N]:文件渲染爲行號表格(HTML 轉義、tab=4、超 4 MiB 截斷橫幅、二進制識別不渲染),目錄渲染爲可繼續點擊進入的列表頁。 - 通過
webserver/index-inject向 GUI 頁面注入一段 head 腳本:攔截髮往/api/host.openPath、/api/host.openTextFile的 RPC,改用window.open('/view?path=…')在新標籤頁展示,並按線上封包形狀僞造成功應答({type:'server-response',rpcId,result:{ok:true,value:{opened:true}}});若新標籤頁被瀏覽器攔截,自動放行原始請求。
常見源碼由 highlight.js 做語法高亮,未知擴展名安全地按純文本展示。這個入口提供兩個配置項:
maxBytes:單次渲染字節上限;intercept:改道的 RPC 方法列表。
安裝與啓用¶
需要先安裝並確認 dsh 可以正常運行。默認從 GitHub 安裝:
dsh plugin --profile web add github:MarvekG/dsh-plugins
dsh web
這裏的 web 是 DSH profile 名稱;如果使用其他 profile,把 web 換成對應名稱。安裝後重啓 DSH Web 生效。
如果不想跟隨倉庫最新代碼,可以在倉庫地址後加 commit SHA 固定版本:
github:MarvekG/dsh-plugins#<sha>
從舊包名升級¶
包已從 @MarvekG/dsh-bug-fix 更名爲 @MarvekG/dsh-plugins,包名變了,不能走「更新」流程平滑切換,舊條目會殘留在 profile 裏。先做卸載,再做安裝:
dsh plugin --profile web remove @MarvekG/dsh-bug-fix
dsh plugin --profile web add github:MarvekG/dsh-plugins
dsh web
卸載與重裝之間不要重啓 DSH Web,避免舊名缺失導致的裝配告警。
典型用法¶
本地調試¶
克隆倉庫後,在倉庫根目錄執行:
dsh plugin --profile web add .
dsh web
手動查看路徑¶
path-viewer 生效後,除了在 DSH Web 裏點擊路徑被改道,也可以直接訪問:
GET /view?path=<絕對路徑>[&line=N]
文件按行號表格渲染,目錄按列表頁渲染,line 參數用於定位行號。
卸載與更新¶
從 profile 移除插件:
dsh plugin --profile web remove @MarvekG/dsh-plugins
更新時先移除舊版本,再安裝新版本:
dsh plugin --profile web remove @MarvekG/dsh-plugins
dsh plugin --profile web add github:MarvekG/dsh-plugins
dsh web
本地調試時,把第二條命令替換爲:
dsh plugin --profile web add .
運行測試¶
在插件目錄執行:
npm test
適用場景與注意¶
兩類場景適合裝這個插件:一是反覆遇到 not strictly wider 報錯、希望冗餘升級字段不再打斷會話;二是在 WSL 環境用 DSH Web,點擊路徑報 spawn powershell.exe ENOENT。兩個問題都沒遇到的話,暫時不必安裝。
使用前確認幾點:
- 安裝或更新後需重啓 DSH Web 生效;插件不會追溯包裹重啓前已存在的 session 工具定義。
- 插件不擴大工作區、不修改
workspaceRoot、不偷偷增加權限。有效權限爲workspace-write時,工作區外的請求仍可能因沙箱邊界被拒絕。 - 插件以當前 dsh 進程權限運行,安裝前應檢查源碼與許可證。項目採用 MIT 許可證,源碼在 GitHub 上可直接審閱。
結尾¶
@MarvekG/dsh-plugins 用兩個獨立入口處理了兩類實際會碰到的兼容性問題:冗餘沙箱升級字段在滿足條件時按當前權限執行,會話不再被打斷;路徑查看改爲純瀏覽器方案,不再依賴從 WSL 喚起 Windows 進程。它也示範了 DSH「一切皆插件」的擴展方式——每個修復一個入口,可單獨加載和卸載。
- 項目地址:https://github.com/MarvekG/dsh-bug-fix
- 社區插件目錄:https://www.skillhub.cn/plugins/MarvekG/dsh-bug-fix