# dsh-fail-guard [English](README.md) | 中文 同一工具连续失败 N 次之后叫停,推一条四段式停手指令(试过什么 / 完整错误原文 / 初判原因 / 需要用户做什么),让它来报告,而不是再试第四种命令写法。 ## 为什么需要外部打断 思考里的复读(「做。做。做。」)一般不是模型退化,是**连续试错**留下的:同一件事失败、换参数、再失败,没有新信息,同一个「该动手了」被反复重下。 提示词层的规则(「连续失败两次就停手」)在这种状态下无效——**那时候模型读的不是提示词,是它自己的 thinking。** 所以打断必须来自外部。 实测依据:一份 74 轮的会话里,前 67 轮短句行占比在 7–48% 波动,从连续十几步失败那一刻断崖跳到 81.6%,之后 85.9% / 89.1% / 91.4%。 ## 安装 ```sh dsh plugin --profile desktop add dsh-fail-guard ``` 重启一次。`cordis.patch.yml` 通过 `dsh.bundle` manifest 自动应用,不用手写 profile 配置。 ## 配置 在 **插件 → dsh-fail-guard → 详情** 里改。字段标了 `.volatile()`,**保存即生效,不用重启**。 | 键 | 默认 | 含义 | | --- | --- | --- | | `threshold` | `2` | 连续失败几次后叫停 | | `sameToolOnly` | `true` | 按工具分别计数;关掉则所有工具共用一个计数 | | `stopText` | 内置 | 推给模型的那条指令 | | `stopSummary` | 内置 | 界面上显示的一行摘要 | | `debug` | `false` | 把事件、计数、叫停写进日志文件 | | `logFile` | `<插件目录>/fail-guard.log` | 日志路径 | 也可以直接写 `cordis.patch.yml`: ```yaml - id: dsh-fail-guard config: threshold: 3 ``` ## 判定 一条 `tool/result` 满足任一条件就算失败:`message.isError === true`,或 `meta.opsShell.exitCode` 存在且非零。两条都要看——退出码为 1 的 shell 命令不会被标 `isError`,而有些工具级错误不带退出码。计数按「会话 + 工具」分组,任何一次成功都清零。 ## 边界 - 不中止刚失败的那次调用(已经发生了) - 不判断「算不算真失败」,任何非零退出都算 - 不重置对话,停手指令只是多一条用户消息 - 不是限流器:叫停后继续失败会重新计数,再达阈值会再叫停一次 ## 许可证 MIT