Jyleaves
dsh-win-bash-fix
Windows Git Bash fix for DeepSeek Harness (dsh): MSYS sandbox conflict + terminal inspector, with the minimal-win collective-thinking preset (we/let's chain)
- Stars
- 0
- Language
- JavaScript
- Created
- Aug 15, 2026
- Updated
- Aug 15, 2026
Introduction
dsh-win-bash-fix
让 DeepSeek Harness (dsh) 在 Windows 上的 Git Bash 真正可用,并附带两套"健康思维链"预设(minimal-win / anchored-win)。
- 修复:Windows 上 bash 工具 100% 启动失败的问题(
PTY shell exited during startup/terminal inspection is unsupported on platform win32) - 预设:persona 强制英文集体思维(few-shot 正反例 + 团队框架)——思维链稳定为
we / let's - 升级不丢:纯运行时补丁(cordis 插件),不修改 dsh 安装文件
Overview
解决什么问题:DeepSeek Harness 在 Windows 上使用 bash 工具(官方 minimal 预设等)时,bash 每次调用都失败:
| 症状 | 报错 |
|---|---|
| bash 每次调用即失败 | Error: PTY shell exited during startup |
| 终端创建被拒绝 | subprocess-local: terminal inspection is unsupported on platform win32 |
模型被迫绕路、反复重试,思维链大量挣扎型 let me(社区俗称"降智") | — |
适合谁:在 Windows 上使用 dsh、希望 bash 工具真正可用、思维链保持健康(we / let's)的用户。
根因(三层,全部在 Windows 上)
- 进程检查器未实现 win32:
dsh-subprocess-local的createProcessInspector()只实现 Linux/macOS,win32 直接throw——每次 spawn 终端都炸。 - MSYS 环境缺失:node-pty 直接拉起 Git Bash 时没有
MSYSTEM/CHERE_INVOKING/MSYS2_PATH_TYPE等环境变量,bash 无法以交互模式启动。 - 🔑 核心根因——沙箱与 MSYS 冲突:dsh 的 Windows 文件沙箱(
dsh-sandbox-windows-acl)用 restricted token(受限令牌) 包一层再执行命令;而 MSYS2 运行时需要创建带用户 SID 的共享内存映射(CreateFileMapping),被受限令牌拒绝(Win32 error 5 (ACCESS DENIED))→ bash 启动即崩溃。
为什么"思维链 let me"之前被认为是玄学
社区把 let me 视为"降智"标记,但真正的原因是:bash 工具在 Windows 上从未成功执行过。模型每次调用 bash 都失败 → 反复重试 → 挣扎型 let me("Let me retry…")刷屏。工具恢复正常后,同一模型同一任务的思维链自动回到健康的 we / let's 集体思维。
重要区分:let me 有两种——
| 类型 | 例子 | 含义 |
|---|---|---|
| 挣扎型(真降智) | "The command failed. Let me retry…" | 工具错误循环 |
| 行动句型(无害) | "Let me check the file…" | 英文第一人称行动计划(模型表达习惯) |
工具正常时不会出现挣扎型;行动句型在 max effort + 开放探索任务 下可能出现(所有预设一致,见使用建议)。
Compatibility
- DSH 版本:在
0.1.0-rc.6(npm 最新)上开发并验证(2026-08-15) - 平台:仅 Windows(win32);Linux/macOS 上插件自动 no-op
- 依赖:Git for Windows(默认
C:/Program Files/Git,可用GIT_ROOT环境变量覆盖) - 模型:DeepSeek V4 Pro(high/max)与 V4 Flash 均验证(见测试矩阵)
Install
方式一:官方命令(推荐)
dsh plugin --profile web add github:Jyleaves/dsh-win-bash-fix
dsh 会自动把包加入 profile 依赖与 dsh.profile.bundles(需要 pnpm,且该 profile 已初始化过——首次可用 dsh web 启动一次初始化)。
方式二:一键复制安装(无需 npm)
git clone https://github.com/Jyleaves/dsh-win-bash-fix.git
cd dsh-win-bash-fix
node install.mjs # 默认 web profile;--profile <name> / --home <dir> 可自定义
方式三:手动
- 复制
lib/index.js与preset-files/到~/.dsh/profiles/web/win-bash-fix/ - 在
~/.dsh/profiles/web/cordis.patch.yml追加:
- insert:
- id: win-bash-fix
name: ./win-bash-fix/index.js
- 把
preset-files/minimal-win/与preset-files/anchored-win/的内容分别复制到~/.dsh/.agent-presets/minimal-win/、~/.dsh/.agent-presets/anchored-win/
装完后:重启 dsh web,浏览器硬刷新(Ctrl+Shift+R)。
Uninstall
# 官方命令方式安装的:
dsh plugin --profile web remove @jyleaves/dsh-win-bash-fix
# 复制方式安装的:删除 profiles/web/win-bash-fix/ 目录,
# 并从 cordis.patch.yml 移除 win-bash-fix 挂载块
删除后可选的清理:~/.dsh/.agent-presets/minimal-win/、~/.dsh/.agent-presets/anchored-win/(如果不再需要)。卸载后重启 dsh 即恢复官方沙箱行为。
Quick start
# 1. 安装(见上)→ 重启 dsh web → 硬刷新浏览器
# 2. 新建会话,选择预设 minimal-win 或 anchored-win
# 3. 模型选 deepseek-v4-pro(默认 high)或 deepseek-v4-flash
# 4. 发任务,例如:"先运行 pwd 和 ls 看看当前目录内容"
预期:bash 工具真实执行(输出 /d/... 路径与文件列表),思维链为 we / let's。
使用建议
| 场景 | 建议 | 原因 |
|---|---|---|
| 开放探索任务("先了解一下项目") | effort = high | high 下 100% 全绿 we/let's |
| 具体任务(改代码/跑实验/读文件) | high 或 max 均可 | max + 具体任务 100% 全绿 |
| max + 开放任务 | 可用但非 100% | 约 2/3 全绿;残留 let me 均为行动句(无害) |
结论:max + 开放任务下的行动句 let me 是模型固有表达(所有预设一致,非插件/预设问题),无法 100% 由提示词压制(v1.0.3 强化 few-shot 后命中率从 ~0% 提升到 ~2/3)。工具正常时不会有挣扎型 let me。
Configuration
| 配置 | 默认值 | 说明 |
|---|---|---|
GIT_ROOT 环境变量 | C:/Program Files/Git | Git for Windows 安装路径(非默认安装时在启动 dsh 前设置) |
DSH_HOME 环境变量 | ~/.dsh | 预设同步目标(install.mjs --home 同理) |
config.gitRoot(插件配置) | 同 GIT_ROOT | 插件条目 config 覆盖(高级) |
Permissions & data
- 访问:仅修改
process.env(MSYSTEM/CHERE_INVOKING/MSYS2_PATH_TYPE/PATH)与~/.dsh/.agent-presets/(首次自动写入两套预设文件) - 不访问:不读取任何用户数据、不发起网络请求、不持有凭据
- 副作用(重要):Windows 上 shell 工具(bash/pwsh)不再走 restricted-token 文件沙箱(因为该沙箱与 MSYS2 根本冲突)。
str_replace_editor等 fs 工具的沙箱独立、不受影响。运行不可信代码时请先卸载本插件。
测试矩阵(DeepSeek V4 Pro,2026-08-15 实测)
| 预设 | effort | 任务类型 | 思维链 | 工具错误 |
|---|---|---|---|---|
| minimal-win | high | 具体任务(读文件/git log/写代码) | we/let's 主导,let_me=0 | 0 |
| minimal-win | high | 开放探索任务 | we/let's 主导,let_me=0 | 0 |
| minimal-win | max | 具体任务 | we/let's 主导,let_me=0 | 0 |
| minimal-win | max | 开放探索任务(v1.0.3 强化后) | ~2/3 全绿;残留为行动句 | 0 |
| anchored-win | high | 开放/具体/写代码/改代码 | we/let's 主导,let_me=0 | 0 |
| anchored-win | max | 开放探索任务 | ~2/3 全绿;残留为行动句 | 0 |
| v4-flash | high/max | 开放探索任务 | 中文思维(无 let_me) | 0 |
对照(未安装本插件,同任务):bash 全失败(PTY 崩溃)、挣扎型 let_me 20–50 次/会话。
Development
npm test # 单元测试(10 用例,无 dsh/无网络,CI 也跑)
node tests/e2e-smoke.mjs # 端到端冒烟(需要本机 dsh web + 模型配额)
- 单元测试覆盖:win32 env 注入(幂等)、PATH 前置、no-op inspector、沙箱 bypass、预设同步(两套)、preset-files YAML 合法性(form-feed 字节检测 + persona 指令存在性)、非 win32 no-op
- E2E 冒烟覆盖:真实 dsh 会话中 bash 成功执行、0 PTY 错误、
let_me < 3 - CI(GitHub Actions):ubuntu + windows 双平台跑单元测试
- 提交前请跑
npm test;改动预设/插件行为后请在本机跑node tests/e2e-smoke.mjs
工作原理
插件在运行时对 dsh 服务做三处猴子补丁(win32 才生效,其他平台零影响):
// 1. 进程级注入 MSYS 环境(子进程自动继承)
process.env.MSYSTEM = "MINGW64";
process.env.CHERE_INVOKING = "1";
process.env.MSYS2_PATH_TYPE = "inherit";
process.env.PATH = "C:/Program Files/Git/bin;C:/Program Files/Git/usr/bin;" + PATH;
// 2. win32 挂载 no-op 终端检查器(绕过 createProcessInspector 的 throw)
// 3. win32 沙箱 confine 直接返回原命令(绕过 restricted-token runner)
补丁作用于运行中的服务对象(prototype),dsh 升级后插件自动重新生效。
预设说明与借鉴
- minimal-win:基于官方
minimal(固定 persona + 持久 bash + str_replace_editor 双工具),persona 追加集体思维指令。 - anchored-win:两阶段锚定机制借鉴自 xiaobright/dsh-anchored-standard(modeltest 项目的评测 preset)——首轮只暴露 bash+edit 两个工具(含输出预算限制与自动上下文抑制),首个工具调用后恢复全量 Standard 目录;在此基础上额外注入集体思维 persona,并将 Windows 下的 shell 统一为 Git Bash(pwsh 禁用,规避 pwsh 心智的 let me 倾向)。
两套预设的 persona 均包含(v1.0.3 强化版):
Reasoning style: always think and reason in English, using first-person
plural ("we", "let's", "we'll", "our"). Never use "let me", "I'll try",
or "I need to" in your reasoning. Be decisive and collective.
Collective phrasing is mandatory in EVERY reasoning sentence:
Wrong: "Let me check the file" Right: "Let's check the file"
Wrong: "I need to explore" Right: "We need to explore"
Wrong: "I should look at" Right: "We should look at"
When asked to explore, understand, or investigate anything, treat it as
a team effort: plan as a team, inspect as a team, report as a team.
Known Limitations and Deferred Work
- Shell 沙箱降级(Windows) — shell 工具不再走 restricted-token 文件沙箱(与 MSYS2 根本冲突);fs 工具沙箱独立不受影响。运行不可信代码时请卸载。
- persistent bash 超时/PTY 偶发重置(win32) — 长命令(>5 分钟默认 timeoutMs)被打断时,dsh 会重置持久 shell;v1.0.5 起 kill 失败也会清理 registry(避免僵尸 + 链式
PTY cleanup failed误报)。超时本身是正常护栏,模型会看到明确的超时提示。 - 仅 win32 — 其他平台 no-op。
- Git Bash 路径硬编码默认值 — 默认
C:/Program Files/Git;非默认安装需设置GIT_ROOT(无 UI 配置)。 - 依赖内部 API(prototype patch) — 锚定
ctx.subprocess/ctx.sandbox的 prototype 方法;若 dsh 重构这些服务内部形状,插件会静默失效,需跟随更新(单元测试会在契约变化时暴露)。 - max + 开放任务的行动句 let me — 模型固有表达,提示词无法 100% 压制(~2/3 全绿);high 下 100% 全绿。残留均为行动句(无害),工具正常时无挣扎型。
- anchored-win 首轮工具受限 — 首轮只有 bash+edit(两工具),复杂任务需要一轮"先读"后晋升全量;恢复会话不会丢失锚定状态。
- v4-flash 思维链为中文 — flash 跟随用户语言用中文思考,无英文代词;无 let_me 且工具零错误,判定健康。需要英文集体思维可自行调整 persona。
- 并发 PTY 未压测 — 多会话高频并发 bash 场景未做压力测试。
Troubleshooting
| 症状 | 处理 |
|---|---|
bash 仍报 terminal inspection is unsupported | 插件未加载:检查 cordis.patch.yml 挂载块 / bundles 是否包含 @jyleaves/dsh-win-bash-fix,重启 dsh |
bash 报 File not found / bash 路径错误 | Git 非默认安装:启动 dsh 前设置 GIT_ROOT(如 D:/Tools/Git) |
| 预设选择器里没有 minimal-win / anchored-win | 检查 ~/.dsh/.agent-presets/ 对应目录(插件首次加载自动同步;也可手动复制 preset-files/ 下子目录) |
| dsh 升级后 bash 又失败 | 升级不会移除插件(运行时补丁);若失败,确认 profile 的 pnpm install 已重新执行(node_modules 更新) |
| 日志位置 | dsh 服务日志:启动终端输出;插件无独立日志(行为可观察) |
| 回滚 | 卸载(见 Uninstall)后重启即恢复官方沙箱行为 |
License & security
- License:MIT(见 LICENSE)
- 安全:插件仅做环境注入与沙箱放行,不执行用户代码、不收集数据。发现安全问题请通过 GitHub Issues(private)或邮件联系维护者,修复后会发布新版本并更新 CHANGELOG。
Changelog
见 CHANGELOG.md。