前言¶
在 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 === truestdio全为'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 目录页。