dsh-plugin-open-in-app-fix:修復 DSH「Open In」打開 Electron 編輯器失敗

前言

在 DeepSeek Harness(DSH)裏做智能體或本地開發時,會話頭部或 Ctrl+Shift+O 的 Open In 菜單是常用入口:把工作區目錄交給 VS Code、Cursor、Windsurf 等編輯器繼續改代碼。若點擊後前端彈出「打開失敗,請重試」(path.openError / “Could not open. Try again.”),問題往往不在編輯器路徑配置,而是 Desktop Host 啓動子進程時繼承了 ELECTRON_RUN_AS_NODE=1,Electron 類編輯器被當成 Node 進程拉起後立即退出。上游模塊打包在 app.asar 裏,用戶側難以直接改;社區插件 dsh-plugin-open-in-app-fix 在宿主進程內對特定 spawn 形狀做補丁,下面介紹其原理、安裝與自檢方式。

這是什麼

dsh-plugin-open-in-app-fix 由維護者 jcy0chenyuan0 發佈,分類爲客戶端插件,倉庫見 GitHub,目錄頁見 SkillHub。一句話定位:修好 DSH 的 Open In …,使「用 VS Code 打開」等操作不再因環境變量繼承而失敗;適用 VS Code、Insiders、Cursor、Windsurf 等 Electron 編輯器。DSH 生態強調「一切皆插件」;SkillHub 等社區目錄爲獨立站點,與 DeepSeek / 幻方無官方從屬關係。

症狀與根因

現象

在 dsh 會話頭部(或 Ctrl+Shift+O)的 Open In 菜單裏選擇 VS Code 等項時,前端彈出 path.openError,文案爲「打開失敗,請重試」或 “Could not open. Try again.”。

根因(倉庫 README 已實測復現)

@deepseek-ai/dsh-host-open-in-app 的 launchDetachedApp 使用 { ...scrubbedParentEnv(), ...options.env } 啓動目標程序。scrubbedParentEnv() 會清理憑據形狀的名字和 DSH_*,但保留 ELECTRON_RUN_AS_NODE。

運行插件的 Desktop Host 本身是 Electron 的 Node 模式子進程(進程鏈:DeepSeek Harness.exe(GUI) → 帶 --expose-internals … dsh-desktop-host … 的子進程 → 插件在此加載),因此環境裏帶有 ELECTRON_RUN_AS_NODE=1。VS Code / Cursor / Windsurf 同爲 Electron 程序,收到該變量後被當作純 Node 進程啓動,在 launchWatchMs 窗口內非零退出 → runLaunch 判爲 failed → 前端報錯。

README 中本機對照(Code.exe <dir>,detached + stdio:ignore):

子進程環境 結果
帶 ELECTRON_RUN_AS_NODE=1 約 64 ms 後 exit code=1,dsh 判失敗
去掉該變量 看護窗口結束時進程仍在運行,dsh 判成功

爲什麼不能直接在別處修

  • 不能在進程級刪除 process.env.ELECTRON_RUN_AS_NODE:dsh-subprocess-local 的 runnerEnvironment() 依賴繼承該變量,讓 process.execPath(Electron)以 Node 模式跑 runner.js;刪掉後 shell / exec 等工具會一起失效。
  • 改不到 open-in-app 模塊:其使用 child_process.spawn 的 ESM 快照綁定(猴補丁無效,Node v24 實測),且模塊在 app.asar 內。
  • 內部 internals.catalog 測試接縫被打包成單文件常量,外部無法掛載。

插件怎麼修

快照函數與實現唯一共享的入口是 ChildProcess.prototype.spawn(options)。本插件只補這一方法,且僅在同時滿足以下條件時,從傳入環境的副本中去掉 ELECTRON_RUN_AS_NODE(及 README 所述的選擇變量處理):

  • detached === true
  • stdio 全爲 'ignore'

app.asar 全量掃描表明,該形狀在發行樹中只有一處(open-in-app 的 GUI 適配器)。subprocess runner、bash 會話、ctx.subprocess 使用結構化 stdio,不受影響,仍繼承變量以 Node 模式啓動。

其餘約定:不改調用方傳入的 env 對象本身(使用過濾後的副本);不修改 process.env、不寫註冊表、不改 app.asar;同進程內冪等;插件 dispose 時還原原方法。

安裝與啓用

首次安裝需在本插件目錄生成 cordis.patch.yml(腳本按當前目錄生成,已 .gitignore,不寫死盤符):

Windows:

.\install.ps1

macOS / Linux:

node install.mjs

隨後在 DSH 中安裝 bundle(路徑替換爲本目錄的絕對路徑):

plugin_manager install_bundle  file:<本目錄的絕對路徑>

裝完後可在 GUI「設置 → 插件」中整體啓用或停用。新 bundle 通常在 profile 熱重載後即生效;若菜單仍報錯,重啓 dsh 桌面端。

換機器時:克隆倉庫到任意目錄,重複上述 install 腳本與 plugin_manager install_bundle 即可;倉庫不包含本機絕對路徑。

運行環境(README):Windows / macOS / Linux 的 DSH Desktop 均適用;Node 20+(DSH 自帶);無第三方依賴。

典型用法與自檢

日常用法無需額外配置:安裝並啓用後,繼續使用會話頭部或 Ctrl+Shift+O 的 Open In 菜單打開目錄即可。

可選一次性自檢:在本插件目錄創建 marker 文件 run-selftest,內容爲要打開的目錄路徑;插件加載時會用與 dsh 相同的啓動方式拉起 VS Code,結果寫入 selftest.json 並刪除 marker,日常啓動不會彈編輯器。

Windows 示例(路徑按實際插件安裝位置調整):

Set-Content -Path "$env:USERPROFILE\.dsh\plugins\open-in-app-fix\run-selftest" -Value (Get-Location).Path
# 讓插件重新加載(重啓 dsh 或重新啓用本 bundle)後:
Get-Content "$env:USERPROFILE\.dsh\plugins\open-in-app-fix\selftest.json"

probe.outcome 爲 launched 表示修補生效;exited / exit code=1 表示補丁未生效,可結合 patched 與 selectorPresentInHostEnv 區分「未加載」與「啓動形狀未匹配」。

倉庫還提供 node test/acceptance.mjs 做補丁前後對照等驗收,可在開發或排查時運行。

卸載

plugin_manager remove_bundle dsh-plugin-open-in-app-fix

或在 GUI 插件頁移除。移除後 Open In 對 Electron 編輯器的行爲回到 dsh 原狀(可能再次失敗)。

適用場景與注意

適合在 DSH Desktop 中頻繁用 Open In 打開 VS Code、Cursor、Windsurf 等工作流的用戶。插件在 dsh-desktop-host 進程內運行,權限與當前 dsh 桌面端一致;安裝前應閱讀 倉庫源碼 與 MIT 許可證,自行評估是否滿足安全與合規要求。

README 指出:真正長期修法應在 dsh 側,launchDetachedApp 組環境時刪除 ELECTRON_RUN_AS_NODE(同倉 PTC 沙箱已有類似過濾);上游修好後本插件可卸載。安裝過程若遇 profile 內 pnpm-lock.yaml 目錄依賴路徑問題,倉庫說明已改爲 file:../../plugins/…,原件備份爲 pnpm-lock.yaml.bak-dsh-fix。

結尾

dsh-plugin-open-in-app-fix 針對 Open In 啓動 Electron 編輯器失敗這一具體故障,用最小範圍的 spawn 補丁去掉 GUI detached 啓動時對 ELECTRON_RUN_AS_NODE 的繼承,而不破壞 subprocess 工具鏈。需要詳情與 issue 請訪問 GitHub 倉庫 與 SkillHub 目錄頁。

羽毛球分组比赛记分
小程序二维码

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

小夜