dsh-pwsh-plugin:DSH 下的常驻 PowerShell 会话与 WSL bash 写边界

前言

在 DeepSeek Harness(DSH)里让智能体跑 Windows 侧 PowerShell,常见有两条路:走 bash 工具进 WSL,或走内置 pwsh 工具。前者会把命令包成 /bin/bash -c "...",外层双引号往往在 PowerShell 看到脚本之前就把 $ 展开;后者能原样传递 $ 和 here-string,但每次调用都是新进程,整条命令还要挤进 Windows 命令行,大约 32,700 字符就会触发 spawn ENAMETOOLONG。若脚本很长、或希望变量、当前目录、已加载模块在多次工具调用之间保留,内置路径都会显得别扭。

下面介绍社区插件 dsh-pwsh-plugin(维护者 citydirector):它在 Harness 里注册 pwsh_run,把脚本正文经 stdin 送进一个常驻的 PowerShell 7 进程;同一仓库还提供 WSL 侧的 llrun 垫片,在 Windows 上替换 bash 工具实现,为 WSL 命令补上可 enforcement 的写边界。插件归类为客户端,在 SkillHub 插件目录 可查到条目;目录站与 DeepSeek / 幻方无官方从属关系,DSH 生态本身是「一切皆插件」的思路,装什么由你在 profile 里选。

这是什么

dsh-pwsh-plugin 是一个发布在 npm 的 DSH bundle(当前 package 版本 0.2.17,MIT 许可证)。它做两件事,且都与内置工具并存、不替换内置 pwsh:

  1. pwsh_run:脚本以 base64 走 stdin 进入常驻 pwsh 7,路上不做转义、不受 32K 命令行上限约束;冷启动大约 400ms 只付一次。README 记载单次实测 91,741 字符仍可执行,完整数据见仓库 FINDINGS.md。
  2. custom-bash(仅 Windows):bundle 通过 cordis.patch.yml 插入一行,指向包内 wsl/custom-bash.mjs,围栏使用随包发布的 llrun 二进制,无需手工拷贝到 /usr/local/bin。说明见 docs/llrun.md。

运行环境要求:DSH 0.2.0-rc.2 或更新(文档写明在 0.2.0-rc.2 与 0.2.1-rc.3 上验过),以及本机已安装 PowerShell 7。package.json 中 engines.dsh 为 >=0.2.0-rc.2 <0.3.0。

核心功能

pwsh_run 与内置工具的差别

层 行为(据 README 归纳)
bash 工具 命令包在 /bin/bash -c "..." 里,$ 与 heredoc 易在外层被处理掉。
内置 pwsh 转义正确,但每 call 新进程,且受 Windows 命令行长度限制。
pwsh_run 脚本正文 stdin 送入常驻会话,上述两类问题在设计上被避开。

工具参数如下(名称与含义以 README 为准):

参数 必填 说明
script 是 PowerShell 脚本正文,原样送达;不要转义 $,不要包 pwsh -c,不要加外层引号。
workdir 否 先 Set-Location;会话有状态,后续调用继承目录。无效路径则本次不执行脚本。
timeoutMs 否 单次超时,默认 120000。

输出规则:stdout 原样返回;warning / verbose 带前缀;异常带 [script threw]。错误流排在 stdout 之后,stdout 与 stderr 的逐行时序不保留;需要顺序时在脚本里自行 2>&1 或 *>&1。

可选配置项包括 pwshPath(默认 pwsh)、idleMs(默认 30 分钟空闲回收)、maxSessions(默认 4)、maxOutputBytes(默认 8MB)、allowUnconfined(默认 false,沙箱策略缺席时拒绝启动而非悄悄放开)。常驻进程在启动时经 ctx.sandbox.confine 包进与内置 pwsh 等价的 workspace 边界;read-only 模式不启动 pwsh_run,文档建议该模式下继续用内置 pwsh。

bundle 会改 profile 什么

安装 bundle 后,cordis.patch.yml 会自动插入两行,无需手改 profile:

  • id: pwsh-run — 工具本体。
  • id: custom-bash — 仅 Windows 启用(disabled: !!js process.platform !== 'win32')。

remove 会连同包一起撤掉这两行。bundle 不会把 Linux 上的官方 tool-bash 关掉;官方行本身已在 Windows 上 disabled。

安装与启用

插件以 DSH bundle 形式安装;下列命令与路径均来自仓库 README,<version> 须换成 npm 上已发布的版本号(例如目录页或 Plugins 页给出的最新版)。

侧栏(桌面端)

Plugins → Add plugin → 填仓库地址 https://github.com/citydirector/dsh-pwsh-plugin,再打开开关。

命令行(desktop profile)

desktop 是保留 profile,只能用桌面安装自带的 dsh.cmd 管理,并设置正确的 DSH_HOME(桌面 App 使用的数据根,默认思路是 ~/.dsh 下的 profile 树):

$dsh = '<桌面端安装目录>\resources\runtime\cli\bin\dsh.cmd'
$env:DSH_HOME = '<DSH_HOME>'

& $dsh plugin --profile desktop add 'dsh-pwsh-plugin@<version>'

本地开发检出可用 file: 规格(硬链接检出,改代码即时生效;registry 规格则是拷贝):

& $dsh plugin --profile desktop add 'file:<检出目录>'

也可直接 npm i dsh-pwsh-plugin,效果等价于让 DSH 解析 registry 包名。README 还提到 github:citydirector/dsh-pwsh-plugin#<tag> 仍可用,但会绕开 pnpm 的 minimumReleaseAge 等供应链策略。

安装后可用非保留 profile 执行 --dump-config,应能看到 # == dsh-pwsh-plugin 以及 - id: pwsh-run。若曾手写 - id: pwsh-run 再装 bundle,会出现重复注册,启动时报 tool "pwsh_run" is already registered;切换方式时须先删手写行再装 bundle。

不装成 npm 依赖时的手写 patch(摘录)

- insert:
    - id: pwsh-run
      name: '<路径>/plugin/index.mjs'
      config:
        pwshPath: 'pwsh'

plugin/ 下 index.mjs、session.mjs、session-server.ps1 三文件须同目录存放。

安装前建议自行浏览 GitHub 源码 与 LICENSE;插件与 DSH 同进程权限运行,沙箱与组合是否完整会影响 pwsh_run 能否启动(例如缺少 ctx.sandboxPolicy 且未设 allowUnconfined: true 时会拒绝启动)。

典型用法

启用 pwsh_run 后,智能体每次调用只提交 script 字段里的 PowerShell 文本,Harness 负责送进常驻会话。下面两步体现文档强调的有状态会话(变量与 workdir 跨调用保留),可在 DSH 里分两次调用验证。

第一次设置工作目录并写入变量:

Set-Location 'C:\your\workspace'
$global:buildTag = 'demo-1'
'ok'

第二次在同一 agent 工作区再调用,脚本不必重复 Set-Location,直接读会话里已有的值:

$global:buildTag
Get-Location

若单次脚本很长,按 README 的设计无需再为命令行长度做分段拼接;仍须遵守 maxOutputBytes 与 timeoutMs,输出截断或超时会按文档说明报错或重建会话。

在 Windows 上启用 bundle 后,bash 工具会走 custom-bash + llrun 路径,写边界与 SSH agent socket 探测等行为以 docs/llrun.md 为准;验收脚本为仓库内 wsl/acceptance.sh(须在未被 custom-bash 再包一层的 WSL 里跑)。

适用场景与注意

更适合谁

  • 经常在 DSH 里跑较长 PowerShell 脚本、或依赖 $ / here-string 且不想和 bash -c 引号层搏斗的 Windows 桌面用户。
  • 需要跨多次工具调用保留 pwsh 变量、Set-Location、已 Import-Module 的模块状态的 agent 工作流。
  • 在 Windows + WSL 组合下,希望 bash 工具对工作区外写入(如 /mnt/c 任意写)有 landlock 等硬边界时,可依赖 bundle 自带的 llrun 路径。

务必留意的边界

  • read-only 沙箱模式:用内置 pwsh,不要用 pwsh_run。
  • 升级插件版本会 dispose 常驻会话,仅存在于会话内的状态会丢失;版本更新走 DSH Plugins 页的 updateBundle / 再次 add 'dsh-pwsh-plugin@<version>',且 profile 里须是 registry semver 规格才便于 DSH 比对版本。
  • workspace-write 下捕获子进程 stdio 的写法可能失败(README 故障表有 node.exe / 管道相关说明);需要输出时改用文档推荐的 Start-Process 重定向等模式。
  • npm 刚发布后的 CDN 延迟、pnpm minimumReleaseAge 导致「更新装到旧版」属于供应链策略,不是权限错误。

更完整的运行时限制见 docs/runtime-notes.zh-CN.md。

结尾

dsh-pwsh-plugin 把「长脚本、少转义、会话状态」和「WSL bash 写边界」收进一个 MIT 的 DSH bundle:装完 bundle 即可用 pwsh_run,Windows 上还可一并启用 custom-bash。若要核对元数据、版本与安装入口,可看 SkillHub 目录页 与 GitHub 仓库 中的 README.zh-CN.md。

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

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

小夜