# 📦 @goodandready/dsh-agent-loop-guard

面向 DeepSeek Harness 的工具调用与智能体流式输出死循环熔断引擎

npm version license DSH Plugin Node version

作者全部项目

🇬🇧 English🇷🇺 Русский🇨🇳 中文说明

如果您喜欢这个插件,请在 GitHub 上为它点亮 Star — 这能让我知道插件对您有用,并鼓励我继续开发和维护它。

🐛 如果您发现 Bug 或希望增加功能,请使用任意语言在 GitHub 上提交 Issue — 我会评估您的建议,并在后续版本中实现有价值的改进。
--- ## ⚡ 核心定位与解决痛点 在自主 AI 智能体执行复杂多阶段研发任务时,遇到工具调用异常、指令模糊或模型幻觉时,极易陷入无限重试死循环:反复读取同一文件、以完全相同的参数反复调用工具却无实际产出,或在流式输出中无限重复相同的文本。此类死循环不仅迅速耗尽上下文 Token 预算,还会导致 UI 卡死与 API 额度浪费。 **`@goodandready/dsh-agent-loop-guard`** 是专为 DeepSeek Harness 打造的原生宿主运行时防死循环熔断插件,无需修改 DSH 核心代码即可提供全面防护: 1. **进度感知型工具防循环(Progress-Aware Epochs)**:仅在工具调用未产生任何状态变化或新证据时判定为死循环。合法的有效迭代(如 `读` ➔ `写` ➔ `读` ➔ `写`)完全不受限制。 2. **文本输出流防死循环(Assistant Output Guard)**:实时监测智能体流式输出,精准识别跨回合或跨步骤的单行及多行 Markdown 段落重复,安全中断生成而不破坏历史对话。 3. **平滑降级至仅回答模式(Answer-Only Mode)**:触发死循环拦截时,向模型返回结构化 DSH 拒绝信息,强制要求模型输出文本向用户说明当前遇到的瓶颈。 4. **日志隐私脱敏**:所有安全警告日志自动对 Token、密码、API Key 等敏感数据进行 `[redacted]` 掩码处理。 --- ## 🏗️ 架构设计 ```mermaid graph TD subgraph DSH ["DeepSeek Harness 核心运行时"] Turn["智能体回合执行
(LLM 推理与工具调用)"] Stream["助手流式输出
(text-delta 与 block-end)"] UserStop["用户指令分析
(停止词识别: stop, halt, 停止)"] end subgraph LoopGuard ["@goodandready/dsh-agent-loop-guard"] ToolInterceptor["ctx.tools.guard 拦截器
(执行前校验 denyReason)"] ProgressEpoch["进度纪元追踪器
(参数与结果哈希签名)"] OutputState["AssistantOutputGuardState
(重复单行与段落判定)"] SafeLogger["脱敏事件日志器
(敏感凭证掩码)"] end subgraph Actions ["防护动作"] Allow["放行工具执行
(产生新结果或有效进展)"] Deny["拦截并强制文本回答
(要求智能体总结原因)"] Cancel["平滑取消当前会话
(keepInbox: false 中止失控输出)"] end Turn -->|agent/pre-step & 工具调用| ToolInterceptor ToolInterceptor --> ProgressEpoch ProgressEpoch -->|确认产生新状态| Allow ProgressEpoch -->|重复无进展或超额| Deny Stream --> OutputState OutputState -->|超出文本重复阈值| Cancel UserStop -->|即刻锁定停止| Deny Deny -.-> SafeLogger Cancel -.-> SafeLogger ``` --- ## ✨ 核心特性深度解析 ### 1. 进度感知型工具调用判定 与盲目统计调用次数的简单计数器不同,本插件精准区分**有效迭代**与**停滞循环**: * **确定性指纹签名**:为调用参数(`callFingerprint`)与返回结果(`resultFingerprint`)生成确定性 JSON 指纹。 * **进度纪元追踪(Progress Epochs)**:一旦操作产生新证据(如文件修改成功、返回新差异或进度 Token),无进展计数器立即重置。 * **网络与 VCS 细粒度隔离**:不同的 HTTP 端点或请求方法(如 Gitea API 的不同资源操作)绝不会因基础域名相同而发生误判。 * **进度工具独立白名单**:专用于维护任务清单的工具(如 `todo_write`)拥有独立的无进展预算,避免更新进度时误触拦截。 ### 2. 拦截代码速查与触发策略 | 拦截代码 | 触发场景 | 默认阈值 | 防护动作 | |:---|:---|:---|:---| | `LOOP_GUARD_STOP` | 用户发送了终止或要求回答的指令(`stop`, `halt`, `cancel`, `停止`, `等等`, `回答`) | 立即触发 | 拦截后续工具调用,强制智能体立即返回文本答复 | | `LOOP_GUARD_DUPLICATE` | 连续以完全相同参数调用工具且返回结果毫无变化 | 1 次重复 | 阻止原地踏步,强制更换执行策略 | | `LOOP_GUARD_REPEAT` | 同一工具组在未产生新状态的情况下连续重复调用 | `maxCallsPerRepeatGroup` (5) | 防止单一工具过度空转 | | `LOOP_GUARD_LIMIT` | 当前回合自上次产出有效进展以来的总无效调用次数超标 | `maxToolAttemptsPerTurn` (64) | 限制单回合探索预算上限 | | `LOOP_GUARD_PROGRESS_LIMIT` | 连续调用进度工具而未产生任何任务变更 | `maxProgressToolCallsPerTurn` (16) | 防止陷入无限修改清单死循环 | | `LOOP_GUARD_OUTPUT` | 智能体在流式输出中重复输出相同单行或完整段落 | `maxRepeatedAssistantLines` (5) | 通过 `agent.cancel()` 安全中断当前输出 | ### 3. 流式文本防死循环机制 * **行规范化**:自动剔除多余空格与不可见回车符,精准捕获带格式的文本重复。 * **段落哈希**:支持最长 `maxAssistantBlockChars` (16,384 字节) 的多行 Markdown 块哈希比对。 * **长耗时工具豁免**:在工具实际执行期间,文本中断检测自动保持静默,避免长任务被误杀。 * **用户输入无损重置**:用户发起新对话轮次时,检测状态自动全量清理重置。 ### 4. 凭证脱敏与日志隐私防护 所有防护告警日志均会自动针对敏感凭证执行脱敏处理: * Bearer 令牌、密码、Cookie 与查询参数凭据(`token=`, `api-key=`, `secret=`)在写入日志前一律替换为 `[redacted]`。 * 对深度嵌套的参数对象执行深度与宽度截断,杜绝超大 JSON 解析引发的内存泄漏。 ### 5. 原生 WebUI 设置卡片、实时防护遥测与一键平滑更新 * **原生设置面板集成**:直接内嵌于 DSH Web 控制台「设置 ➔ 插件 ➔ 插件设置」卡片列表中(`settings.plugin.item`, order 95)。 * **对齐 DSH 设计规范**:完全基于 DSH 标准设计令牌变量(`--dsw-alias-*`)与无障碍标签绑定(`htmlFor`/`id`),搭配轻量级平滑展开 Chevron 图标,零外部重型 UI 库依赖。 * **实时防护遥测看板**:在设置卡片中直观呈现当前运行时拦截的死循环总数(`LOOP_GUARD_DUPLICATE`, `LOOP_GUARD_REPEAT`, `LOOP_GUARD_LIMIT`, `LOOP_GUARD_OUTPUT`),支持通过 `/api/@goodandready/dsh-agent-loop-guard/telemetry` 安全端点一键重置计数。 * **一键无缝在线更新**:卡片自动联动 npm 官方源检查最新版本,支持通过经过鉴权的本地环回 API(`/api/@goodandready/dsh-agent-loop-guard/update`)在后台安全完成版本升级。 --- ## 📦 快速安装 通过 DeepSeek Harness CLI 一键安装: ```bash dsh plugin --profile web add @goodandready/dsh-agent-loop-guard ``` 重启 DSH 并刷新浏览器工作区。 --- ## ⚙️ 配置指南 在 `config.yaml` 或 Web UI 设置面板中配置: ```yaml # config.yaml dsh-agent-loop-guard: maxToolAttemptsPerTurn: 64 maxProgressToolCallsPerTurn: 16 progressToolNames: - todo_write maxCallsPerRepeatGroup: 5 blockExactDuplicates: true assistantOutputGuard: true maxRepeatedAssistantLines: 5 maxRepeatedAssistantBlocks: 5 maxAssistantBlockChars: 16384 ``` ### 配置参数参考表 | 参数名 | 类型 | 默认值 | 功能说明 | |:---|:---|:---|:---| | `maxToolAttemptsPerTurn` | `number` | `64` | 单回合最大无进展工具调用预算。设为 `0` 可禁用此聚合上限。 | | `maxProgressToolCallsPerTurn` | `number` | `16` | 进度标记工具(`todo_write`)连续无进展调用的上限。 | | `progressToolNames` | `array` | `["todo_write"]` | 标记任务进度的工具名称数组。 | | `maxCallsPerRepeatGroup` | `number` | `5` | 同一组工具未产生新结果时允许调用的最大次数。 | | `maxCallsPerToolPerTurn` | `number` | `5` | *(已废弃)* `maxCallsPerRepeatGroup` 的向后兼容别名。两者同时存在时优先使用 `maxCallsPerRepeatGroup`。UI 卡片中有意隐藏以避免混淆。 | | `strictTools` | `array` | `[]` | 受到更严格重复调用限制的敏感/修改类工具名称列表。 | | `strictToolLimit` | `number` | `3` | `strictTools` 列表中工具的最大允许重复次数。 | | `blockExactDuplicates` | `boolean` | `true` | 是否立即拦截结果毫无变化的连续相同调用。 | | `dryRunMode` | `boolean` | `false` | 审计模式:记录告警与遥测指标,但不实际拦截工具调用。 | | `assistantOutputGuard` | `boolean` | `true` | 是否开启助手流式文本输出防死循环监测。 | | `maxRepeatedAssistantLines` | `number` | `5` | 触发输出中断的连续相同单行阈值。 | | `maxRepeatedAssistantBlocks` | `number` | `5` | 触发输出中断的连续重复段落阈值。 | | `maxAssistantBlockChars` | `number` | `16384` | 捕获用于段落指纹比对的最大字符数。 | --- ## 🧪 测试与校验 运行全部 51 个自动化单元与集成测试及静态代码检查: ```bash npm test npm run check ``` --- ## 📄 开源许可证 * **开源许可证**: MIT © [GooDAnDReaDY](https://github.com/GooDAnDReaDY) * **更新历史**: 完整版本演进历史与特性发布记录详见 [CHANGELOG.md](CHANGELOG.md)。