前言¶
在 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:
pwsh_run:脚本以 base64 走 stdin 进入常驻 pwsh 7,路上不做转义、不受 32K 命令行上限约束;冷启动大约 400ms 只付一次。README 记载单次实测 91,741 字符仍可执行,完整数据见仓库 FINDINGS.md。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。