clearkurt
dsh-win-terminal-inspector
Windows (win32) terminal inspection for DSH persistent/PTY shells
- Stars
- 2
- Language
- JavaScript
- Created
- Aug 14, 2026
- Updated
- Aug 14, 2026
Introduction
dsh-win-terminal-inspector
DSH(DeepSeek Harness)Windows 平台的 terminal inspection 插件:为 persistent/PTY 终端(Claude Code 风格的持久化 bash)补齐 win32 上的进程监视能力。
解决的问题
@deepseek-ai/dsh-subprocess-local 的 createProcessInspector() 只支持 linux/darwin,
在 win32 上创建 PTY 终端会话(spawnTerminal())时抛出硬错误:
Error: subprocess-local: terminal inspection is unsupported on platform win32
本插件通过 LocalSubprocessRuntime 公开的 terminalInspector 测试钩子注入
WindowsProcessInspector,不修改任何 node_modules 文件:
- 包装运行时的
spawnTerminal,为每个终端创建独立的 inspector; - 把生成的 node-pty 终端 attach 到 inspector,用于通过 ConPTY 输入发送真正的
Ctrl-C(写入
\x03,等价于真实控制台按键,经验证可正确中断 Git Bash 前台命令); - 插件卸载(dispose)时恢复原
spawnTerminal,完全可逆。
接口实现(与 ProcessInspector 完全一致)
| 方法 | Windows 语义 |
|---|---|
foregroundPgid(shellPid) | shell 存活时返回 shellPid(整个 ConPTY 树共享同一控制台,即一个“进程组”) |
isStdinWaiting(pgid) | 恒为 false(Windows 无法读取其他进程的 syscall;就绪判定由 dsh-terminal-bash 的提示符机制承担,与 macOS 实现一致) |
processTree(rootPid) | 基于 Win32_Process 父子关系,children-first、防环,与 POSIX 实现同序 |
processSession(sessionId) | 恒为 [](Windows 无 POSIX session 概念,控制台树即会话边界) |
isAlive(identity) | pid + UTC 创建时间双重比对,防 PID 复用 |
signalGroup(pgid, signal) | SIGINT/SIGBREAK → 向 ConPTY 输入写 \x03;SIGTERM/SIGKILL → taskkill /T /F 整树强杀 |
signalProcess(identity, signal) | 存活校验后 TerminateProcess(Windows 控制台进程无优雅 TERM) |
进程表后端:powershell.exe -NoProfile -NonInteractive + Get-CimInstance Win32_Process
(pid/ppid/session/CreationDate,CreationDate 兼容 DateTime 与 CIM 字符串两种形态),
300ms TTL 缓存,避免 25ms 轮询下重复拉表。
安装(以 web profile 为例)
-
把本包复制到 profile 的 plugins 目录:
<DSH_HOME>\profiles\web\plugins\dsh-win-terminal-inspector\ -
在
<DSH_HOME>\profiles\web\cordis.patch.yml的顶层数组中追加:- insert: - id: win-terminal-inspector name: ./plugins/dsh-win-terminal-inspector/index.js -
长驻进程(如
dsh web)会热加载该 patch;否则重启dsh web。
让持久化 bash 用上 Git Bash
@deepseek-ai/dsh-terminal-bash 默认 shellPath: /bin/bash,在 Windows 上需在
所用 preset 里覆写(例如复制 minimal preset 后改 terminal-bash 行):
- id: terminal-bash
name: '@deepseek-ai/dsh-terminal-bash'
config:
timeoutMs: 300000
shellPath: C:\Program Files\Git\bin\bash.exe
shellArgs: ['--noprofile', '--norc', '-i']
不要用
--login -i。Git Bash 的登录 shell 会执行登录脚本并覆写PS1, 打破dsh-terminal-bash的受控提示符就绪契约(表现为 prompt 探针一直不 满足)。--noprofile --norc -i才保留受控提示符,且/usr/bin仍在PATH上。
配套 preset:minimal-win
光装本插件还不足以让“极简模式”的持久化 bash 在 Windows 上真正跑起来——还需 两件事一起做:
- 给 terminal-bash 指定 Git Bash(见上一节),否则默认
/bin/bash不是 Windows 可执行路径,spawn 会失败(File not found)。 - 让 shell 不走 windows-acl 受限令牌。默认
workspace-write会把每次 spawn 包进WRITE_RESTRICTEDrunner,而 MSYS 运行时在该令牌下无法创建信号 管道(fatal error - couldn't create signal pipe, Win32 error 5),bash 启动即退。
minimal-win 即一个把这两点都做好的本地 preset:复制 minimal 后,在
persistent-shell 组里带上一个入口级 realm 的 sandbox-policy 并 pin 到
danger-full-access(shell 无文件沙盒,与该 preset 本就裸奔的本地文件系统
一致),同时把 terminal-bash 指到 Git Bash:
- id: persistent-shell
name: cordis:group
group: true
isolate:
terminals: true
sandboxPolicy: true
config:
- id: pty
name: '@deepseek-ai/dsh-terminal'
- id: sandbox-policy
name: '@deepseek-ai/dsh-sandbox-policy'
config:
mode: danger-full-access
workspaceRoot: !!js process.env.DSH_CWD ?? process.cwd()
- id: terminal-bash
name: '@deepseek-ai/dsh-terminal-bash'
config:
timeoutMs: 300000
shellPath: C:\Program Files\Git\bin\bash.exe
shellArgs: ['--noprofile', '--norc', '-i']
- id: persistent-bash
name: '@deepseek-ai/dsh-tool-bash-persistent'
config:
timeoutMs: 300000
description: |-
Run commands in a bash shell (Git Bash on Windows)
* This shell runs unconfined (danger-full-access): no file sandbox on shell commands.
* State is persistent across command calls and discussions with the user.
代价:
minimal-win的 shell 不受文件沙盒约束。若需要受限模式也能跑 Git Bash,得改官方dsh-sandbox-windows-acl的令牌构造,属于另一项包级改动。 另外,把运行该 preset 的会话手动切回workspace-write/read-only(session 级sandbox/mode会覆盖 preset 默认值)会重新触发 MSYS 信号管道 错误。
验证
node test\inspector.test.mjs # 进程树/session/存活/信号 单元测试
node test\smoke-terminal.mjs # spawnTerminal + 持久化 bash 会话端到端测试
回滚
- 从
cordis.patch.yml删除win-terminal-inspector条目(热加载生效),或整包删掉 plugins 目录后重启dsh web; - 插件未修改任何官方包文件,删除即完全还原。
已知限制
- Windows 无 POSIX 进程组/会话,
foregroundPgid以 shell pid 作为整树组 id; isStdinWaiting恒为 false(就绪判定走提示符路径,与 macOS 一致);- SIGTERM 与 SIGKILL 在 Windows 上均为强杀(TERM→grace→KILL 的时间阶梯仍保留)。