@MarvekG/dsh-plugins:修復 DSH 冗餘沙箱升級報錯與 WSL 路徑打開失敗

前言

用 DSH Web 做日常開發時,有兩類報錯比較容易碰到。一類是 session 權限已經切到 danger-full-access 之後,模型重試仍然攜帶 sandbox_permissionsjustification 字段,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 bashpwshwriteedit 工具。只有以下條件同時滿足時,它才刪除升級字段並按當前權限執行:

  1. sandbox_permissions 是該工具 schema 明確公開的枚舉值;
  2. justification 是非空字符串;
  3. 請求權限不寬於當前調用、當前 session 的有效 sandbox 權限。

此時請求只是冗餘聲明,不彈審批,也不再報 not strictly wider

真正的權限升級和非法輸入仍走原流程:

  • read-only → 更高權限:繼續申請審批;
  • workspace-writedanger-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 進程。具體分兩步:

  1. 在同一個 web 服務上註冊帶回環圍欄的 GET /view?path=<絕對路徑>[&line=N]:文件渲染爲行號表格(HTML 轉義、tab=4、超 4 MiB 截斷橫幅、二進制識別不渲染),目錄渲染爲可繼續點擊進入的列表頁。
  2. 通過 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。兩個問題都沒遇到的話,暫時不必安裝。

使用前確認幾點:

  1. 安裝或更新後需重啓 DSH Web 生效;插件不會追溯包裹重啓前已存在的 session 工具定義。
  2. 插件不擴大工作區、不修改 workspaceRoot、不偷偷增加權限。有效權限爲 workspace-write 時,工作區外的請求仍可能因沙箱邊界被拒絕。
  3. 插件以當前 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
羽毛球分组比赛记分
小程序二维码

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

小夜