DSH Plugin Store
Back to home

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
Other
GitHub repo

Introduction

dsh-win-terminal-inspector

DSH(DeepSeek Harness)Windows 平台的 terminal inspection 插件:为 persistent/PTY 终端(Claude Code 风格的持久化 bash)补齐 win32 上的进程监视能力。

解决的问题

@deepseek-ai/dsh-subprocess-localcreateProcessInspector() 只支持 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 为例)

  1. 把本包复制到 profile 的 plugins 目录:

    <DSH_HOME>\profiles\web\plugins\dsh-win-terminal-inspector\
    
  2. <DSH_HOME>\profiles\web\cordis.patch.yml 的顶层数组中追加:

    - insert:
        - id: win-terminal-inspector
          name: ./plugins/dsh-win-terminal-inspector/index.js
    
  3. 长驻进程(如 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 上真正跑起来——还需 两件事一起做:

  1. 给 terminal-bash 指定 Git Bash(见上一节),否则默认 /bin/bash 不是 Windows 可执行路径,spawn 会失败(File not found)。
  2. 让 shell 不走 windows-acl 受限令牌。默认 workspace-write 会把每次 spawn 包进 WRITE_RESTRICTED runner,而 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 的时间阶梯仍保留)。