← 返回列表
未验证
让 Windows 上的 DSH 在 WSL2 里跑命令与沙箱
尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/9/16 · 已提供中文文档
在 Windows 主机上,从 WSL2 内部运行 DeepSeek Harness(dsh)执行环境:一个由 wsl.exe 支持的 ctx.ssh 服务,原样复用官方 dsh-ssh 提供程序和辅助工具。
综合分
30
GitHub 分
30
用户评分
—
★ Stars
0
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add lyqteemo/dsh-wsl-remote该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/16(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-fs-ssh@deepseek-ai/dsh-sandbox-ssh@deepseek-ai/dsh-ssh@deepseek-ai/dsh-subprocess-ssh@deepseek-ai/dsh-base用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
description: "让 Windows 上的 DSH 把文件、命令、终端与沙箱执行全部放进同一台机器的 WSL2 发行版:用 wsl.exe 实现官方 dsh-ssh 家族所需的 ssh 服务,官方 provider 与 helper 原样复用。"
kind: "package-bundle"
dsh-wsl-remote
Repository: · License: MIT
让 Windows 上的 DSH 把文件、命令、终端与沙箱执行全部放进同一台机器的 WSL2 发行版里,工作区用 \\wsl.localhost\\... 打开。
这是 ZCode「桌面端 + 远端 runtime」模型的一个 DSH 实现,但换了一条更短的路:DSH 官方已经有远端 POSIX 执行家族(@deepseek-ai/dsh-fs-ssh / -subprocess-ssh / -sandbox-ssh)和配套 helper,它们唯一的硬依赖是一个名为 ssh 的服务。本插件把那个服务用 wsl.exe 实现出来,于是官方三个 provider 与官方 helper 全部原样复用,没有 fork、没有改动上游代码,也不需要 SSH 服务端。
为什么能这样接
| 环节 | 官方 SSH 家族 | 本插件 |
|---|---|---|
| 客户端 provider | fs-ssh / subprocess-ssh / sandbox-ssh | 原样复用(只依赖 ctx.ssh 的 4 个方法) |
| RPC 协议 | @deepseek-ai/dsh-ssh/protocol 的 4 字节长度前缀 JSON 双向 RPC | 原样复用 |
| 握手 | hello + helper 文件 SHA-256 比对 | 原样复用 |
| helper | 官方 dsh-ssh 的 lib/helper.js(内嵌 cordis 的 mini-DSH) | 原样复用,装进 WSL |
| 传输 | OpenSSH 连接复用 + 转发 Unix 套接字 + 每流 TLS-PSK | 换成 wsl.exe stdio |
| 流(stdin/stdout/stderr/控制/终端) | 客户端连转发到远端的 Unix 套接字 | 换成 per-stream relay 进程:wsl.exe -- node -e ,relay 在发行版内部终止 TLS-PSK 握手并把裸字节接回自己的 stdio |
helper 发布 stream 的方式没变({ path, capability },capability 是 256 位 PSK),所以我们只需要在 WSL 侧做一个会说 TLS-PSK 的 relay,主机侧把它包成 net.Socket 形状的 Duplex——subprocess-ssh 完全不知道中间发生了什么。
路径:工作区在 Windows 侧是 UNC(\\wsl.localhost\\home\\),插件在每个请求进入 wire 之前把 fs.resolve/fs.lstat 的 path/cwd、process.prepare 的 cwd、以及 sandbox/fs.write/fs.edit 的 policy.workspaceRoot 改写成 WSL 绝对路径;helper 自己铸造的 target 身份与 argv 一律不动。跨发行版的 UNC 会直接报错而不是读错盘。
工具平台翻转:dsh-base 用 process.platform === 'win32' 选 shell,Windows 上会禁用 tool-bash/bash-sandbox 并启用 tool-pwsh/pwsh-sandbox。但执行世界是 Linux,所以插件补丁把这两对翻转回来。
已验证到什么程度
在 Windows 11 + WSL2 发行版上实测:
| 验证 | 结果 |
|---|---|
| wsl.exe stdio 二进制安全(200KB 随机字节往返) | 一致 |
| 长驻进程 + 双向流式 stdio | 通过 |
| 路径映射单测(UNC / wsl$ / 盘符 / 跨发行版拒绝 / 参数重写边界) | 12/12 |
| 经真 wsl.exe 对 stub helper 做握手 + 路径映射 + TLS-PSK 流中继 | 3/3 |
| 经真 wsl.exe 对官方真 helper 端到端:fs.write(createIfAbsent) → fs.stat → fs.readText → fs.edit(版本守卫) → fs.list → 真 bash 进程经中继取 stdout → process.done 退出码 0;且子进程读到的正是文件工具写入的内容 | 通过(594ms) |
| 官方三 provider 挂在 WslConnection 上跑生产代码路径:ctx.fs 10 个方法、ctx.subprocess 的 RemoteProcess(piped 双流 + 生命周期)、collected-output(走 stream RPC 而非裸管道)、ctx.sandbox.confine(远端返回真实 facts)、spawnTerminal PTY | 通过(约 6s) |
| Windows 侧验收:Windows Node 驱动、helper 在 WSL 内执行(scripts/windows-verify.ps1 -Full,包暂存到 Windows 本地目录并装 Windows 原生依赖) | 4/4 文件、17/17 用例 |
| 兼容源码 HEAD:把 @deepseek-ai/dsh-ssh / -fs-ssh / -subprocess-ssh / -sandbox-ssh 换成源码 checkout()的构建产物后,同一 provider E2E 仍通过 | 通过 |
| 源码 CLI 组合:scripts/windows-harness-compose.ps1(用源码 checkout 的 CLI + 临时 DSH_HOME)组合本插件补丁 | dump exit 0,所覆盖的基座行 id 全部命中 |
| 补丁组合(dsh --profile web --patch --dump-config) | 退出码 0,insert/disable 全部按预期落位 |
尚未验证:Web 侧文件树/文档预览/工作区选择器(读取走 ctx.fs,理论上会跟着走远端,未实测);PTC(Node bootstrap);多会话并发。
把所有用例一起跑:DSH_WSL_E2E=1 node --test tests/.test.mjs → 17/17(12 路径映射单测 + 3 个真 wsl.exe 集成 + 1 个真 helper 端到端 + 1 个官方 provider 生产路径)。relay 源码契约另有 5 个用例,合计 22。
独立接线官方 provider 时有个坑:SandboxPolicyService 自身 inject sessionProjections,必须先 plug SessionProjectionRegistry,否则 policy 与所有下游 provider 的 fiber 会一直 pending,表现为 ctx.fs 为 undefined。(真实 profile 里 dsh-base 已提供该服务,插件本身不受影响。)
Windows 侧安装
前提:Windows 有 Node ≥ 22.19,WSL2 发行版里有 Node ≥ 22.19。
1) 装 dsh(alpha 包不在 npmmirror,必须指定官方 registry)
npm i -g @deepseek-ai/dsh@0.1.6-alpha.1 --registry=https://registry.npmjs.org
2) 部署官方 helper 到 WSL(默认装进发行版的 ~/.dsh-wsl,不碰发行版全局 npm)
在本仓库内执行;--distro 省略时取 $DSH_WSL_DISTRO,再取默认发行版
node scripts/deploy-helper.mjs
它会打印一组 DSH_WSL_ 值。补丁从环境变量读取,把这些导出去(或写进系统环境):
DSH_WSL_WORKSPACE / DSH_WSL_HELPER / DSH_WSL_HELPER_HASH ← 必填
DSH_WSL_DISTRO / DSH_WSL_USER / DSH_WSL_NODE ← 可选,有默认值
3) 把插件放到 Windows 本地目录(WSL 的 node_modules 是 Linux 原生的,不要带过去)
$src = '' # 例:\\wsl.localhost\\home\\code\dsh-wsl-remote
$dst = '' # 例:D:\dsh-plugins\dsh-wsl-remote
Remove-Item -Recurse -Force $dst -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force $dst | Out-Null
Copy-Item "$src\lib","$src\scripts","$src\tests","$src\package.json","$src\cordis.patch.yml","$src\README.md" $dst -Recurse -Force
4) 注册进 web profile,并把依赖装到位
Set-Location C:\ # 工作目录不能是 UNC,否则 pnpm/cmd 会失败
dsh plugin --profile web add link: # 若尚未注册
powershell -ExecutionPolicy Bypass -File \scripts\windows-install-plugin.ps1
该脚本默认用 PATH 上的 dsh;要指定源码 CLI 用 -Dsh \apps\cli\lib\bin.js
5) 先看组合树,再重启
dsh --profile web --dump-config
dsh web
为什么第 4 步必须跑那个脚本:pnpm add link: 只创建符号链接,不会安装被链目录的依赖;而 Node 按包的真实路径解析 import,所以插件目录自己的 node_modules 必须存在。同时补丁里的 @deepseek-ai/dsh-fs-ssh / -subprocess-ssh / -sandbox-ssh 三行是按包名从 profile 的 node_modules 解析的,而它们把 @deepseek-ai/dsh-ssh 声明为 peer(autoInstallPeers: false 时不会自动装),所以这四个包都要显式加进 profile。只做 link: 的表现正是:wsl-connection / fs-ssh / subprocess-ssh / sandbox-ssh: failed to import,并连带 bash-sandbox、tool-bash、permission、ptc-runtime、workspace-files 等约 12 行保持 pending。
然后在 Web GUI 里把工作区加成 \\wsl.localhost\\home\\。
配置项(wsl-connection 行)
行配置由 cordis.patch.yml 从环境变量读取(也可在 profile 的补丁层里直接写死):
| 字段 | 来源 | 说明 |
|---|---|---|
| distro | DSH_WSL_DISTRO ?? Ubuntu | WSL 发行版名 |
| user | DSH_WSL_USER | 以哪个 Linux 用户运行 helper 与所有工作区进程;省略时用发行版默认用户 |
| workspace | DSH_WSL_WORKSPACE(必填) | 工作区路径,支持 UNC / 盘符 / POSIX |
| helper / helperHash | DSH_WSL_HELPER / DSH_WSL_HELPER_HASH(必填) | WSL 内 helper 绝对路径与小写 SHA-256(握手时比对) |
| node | DSH_WSL_NODE ?? node | WSL 内 Node 可执行文件 |
| mountPrefix | /mnt | 盘符路径的挂载前缀 |
| leaseMs | 30000 | helper 租约;心跳丢失则远端自行清理 |
| requestTimeoutMs / maxFrameBytes / maxPending | 30000 / 64MiB / 128 | 握手期限 / 单帧上限 / 并发上限 |
| bootstrapPath + bootstrapHash | 省略 | 要用 PTC 时成对提供 |
必填项缺失时,该行会在加载时失败(profile 因此无法启动),错误信息会点名每一个缺失字段并给出对应命令(scripts/deploy-helper.mjs)。导出的 schema 故意保持宽松,正是为了让这条信息可操作:loader 会在 apply 之前校验它,否则只会以一个光秃秃的逐字段错误中断启动。
测试
cd dsh-wsl-remote
npm install --registry=https://registry.npmjs.org # 开发依赖;alpha 包需官方 registry
node --test tests/.test.mjs # 单测 + wsl.exe 集成测试
DSH_WSL_E2E=1 node --test tests/.test.mjs # 再加真 helper 与官方 provider 生产路径
DSH_WSL_DEBUG=1 ... # 打印 relay 的 stderr,便于排查流问题
npm run lint # 零依赖语法检查(遍历所有 JS 文件)
npm run check:patch-rows # 本补丁涉及的基座行 id 是否仍然存在
测试的机器相关输入都由环境变量提供,缺省值是中性的:DSH_WSL_TEST_DISTRO、DSH_WSL_TEST_NODE、DSH_WSL_TEST_WORKSPACE、DSH_WSL_TEST_WORKSPACE_POSIX、DSH_WSL_TEST_HELPER、DSH_WSL_E2E_HELPER、DSH_WSL_E2E_HELPER_LOCAL、DSH_WSL_E2E_WORKSPACE。拿不到 wsl.exe 或发行版时,相关用例会自行 skip。
单独跑某个用例(避免把 stub-helper.mjs 当测试文件):node --test tests/providers.e2e.test.mjs。
Windows 侧验收
下面的脚本会自己推导发行版($DSH_WSL_DISTRO → 默认发行版)、插件目录(脚本自身位置)与 helper 路径(发行版 $HOME),并把 CLI 作为参数:-Dsh \apps\cli\lib\bin.js,默认用 PATH 上的 dsh。
用 Windows Node 跑全套(helper 仍在 WSL 内执行)
powershell -ExecutionPolicy Bypass -File scripts\windows-verify.ps1
powershell -ExecutionPolicy Bypass -File scripts\windows-verify.ps1 -Full
用源码 checkout 的 CLI 验证补丁能与该 revision 的 bundle 组合
powershell -ExecutionPolicy Bypass -File scripts\windows-harness-compose.ps1 -Dsh \apps\cli\lib\bin.js
验证本机 dsh 能真正调用已配置的模型(搬完模型配置后建议先跑一次)
powershell -ExecutionPolicy Bypass -File scripts\windows-model-check.ps1
起一个临时 web 实例,抓启动诊断(哪些行 failed/pending)
powershell -ExecutionPolicy Bypass -File scripts\windows-web-probe.ps1
windows-model-check.ps1 用 headless 模板临时建一个 profile、跑一次真实请求、再删掉它,因此它验证的是当前 DSH_HOME(默认 %USERPROFILE%\.dsh)里的模型配置(provider 路由 + 凭据)而不是 GUI。手工编辑 settings.yaml 时注意:reasoningEfforts 里的 off: 是字符串键,用 YAML 1.1 工具(PyYAML、部分 yq)往返会被解析成布尔并写成 false:,那会让 provider 配置失效并以 NO_ADAPTER 失败。
windows-verify.ps1 会把包暂存到 Windows 本地目录(node --test 不接受 UNC 参数、cmd.exe 也不接受 UNC 工作目录),在那里装 Windows 原生依赖,并给每个 e2e 文件分配独立工作区;默认用完即删(-Keep 保留)。它使用私有 npm cache,以免受机器上 %LocalAppData%\npm-cache 状态影响。
已知限制与风险
- 主机侧文件沙箱不再约束执行。文件效果由远端 helper 的沙箱策略执行,helper 以 WSL 用户的权限运行;danger-full-access 下 helper 会拒绝包装 argv(沿用官方语义)。注意 wsl.exe interop 本身可以越过 DSH 主机侧的文件沙箱。
- 不是"远端工作区视图"的完整实现。Web 的文件树/预览是否跟随远端未验证;本版本目标只是执行侧。
- 无重连、无重放。发行版停止、helper 退出或管道断开会让所有在途操作失败;已完成的远端变更不会被撤销。
- PTC(Node bootstrap)未配置;多会话并发未验证。
- 发行版与 Windows 必须都能跑到 Node ≥ 22.19。
- 依赖 alpha 版本的上游包(0.1.6-alpha.1),上游破坏性变更会影响本插件。
目录
- lib/index.js — ssh 服务(apply 插件形态,不 import cordis,避免双实例)
- lib/mapping.js — UNC/盘符 ↔ WSL 路径映射与请求参数重写
- lib/relay-code.js — 注入 WSL 的 per-stream TLS-PSK relay 源码
- lib/types/index.d.ts — 面向消费方的手工类型面
- scripts/deploy-helper.mjs — 在发行版内安装官方 helper 并打印配置
- cordis.patch.yml — bundle 补丁:插入四行、停用本地三行、翻转 shell 工具,从环境变量读部署事实
- tests/ — 单测、wsl.exe 集成测试、真 helper 端到端测试、relay 源码契约;tests/fixtures/ 放 stub helper
- scripts/windows-*.ps1 — Windows 侧安装与验收脚本(自推导路径)扫码进群