@goodandready/dsh-agent-loop-guard

securitytested: passnpmMIT

Fail-closed runtime tool-call loop guard for DeepSeek Harness.

下载量 / Downloads
1,666
依赖体积 / node_modules
12.26 MB
测试时间 / Tested
2026-11-06
DSH 版本 / Version
0.2.2-rc.1

Install

dsh plugin --profile web add @goodandready/dsh-agent-loop-guard

Sandbox test results

StageResult
1 install✓
2 list✓
3 mount✓
4 boot—

Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).

README

📦 @goodandready/dsh-agent-loop-guard

<div align="center">

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

<p align="center">

<a href="https://www.npmjs.com/package/@goodandready/dsh-agent-loop-guard"><img src="https://img.shields.io/npm/v/@goodandready/dsh-agent-loop-guard.svg?style=for-the-badge&color=6366f1&labelColor=1e1b4b" alt="npm version"></a>

<a href="LICENSE"><img src="https://img.shields.io/github/license/GooDAnDReaDY/dsh-agent-loop-guard.svg?style=for-the-badge&color=10b981&labelColor=064e3b" alt="license"></a>

<a href="https://github.com/topics/dsh-plugin"><img src="https://img.shields.io/badge/DSH-Plugin-8b5cf6.svg?style=for-the-badge&labelColor=2e1065" alt="DSH Plugin"></a>

<a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node-20%2B-f59e0b.svg?style=for-the-badge&labelColor=451a03" alt="Node version"></a>

</p>

<p align="center">

<a href="https://goodandready.app/"><img src="https://img.shields.io/badge/作者全部项目-goodandready.app-ff4500.svg?style=for-the-badge&logo=rocket&logoColor=white&labelColor=1a1a2e" alt="作者全部项目"></a>

</p>

<p align="center">

<a href="README.md"><b>🇬🇧 English</b></a> •

<a href="README.ru.md"><b>🇷🇺 Русский</b></a> •

<a href="README.zh.md"><b>🇨🇳 中文说明</b></a>

</p>

<table align="center">

<tr>

<td align="center">

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

<br><br>

🐛 <strong>如果您发现 Bug 或希望增加功能</strong>,请使用任意语言在 GitHub 上提交 Issue — 我会评估您的建议,并在后续版本中实现有价值的改进。

</td>

</tr>

</table>

</div>


⚡ 核心定位与解决痛点

在自主 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] 掩码处理。


🏗️ 架构设计

graph TD
    subgraph DSH ["DeepSeek Harness 核心运行时"]
        Turn["智能体回合执行<br/>(LLM 推理与工具调用)"]
        Stream["助手流式输出<br/>(text-delta 与 block-end)"]
        UserStop["用户指令分析<br/>(停止词识别: stop, halt, 停止)"]
    end

    subgraph LoopGuard ["@goodandready/dsh-agent-loop-guard"]
        ToolInterceptor["ctx.tools.guard 拦截器<br/>(执行前校验 denyReason)"]
        ProgressEpoch["进度纪元追踪器<br/>(参数与结果哈希签名)"]
        OutputState["AssistantOutputGuardState<br/>(重复单行与段落判定)"]
        SafeLogger["脱敏事件日志器<br/>(敏感凭证掩码)"]
    end

    subgraph Actions ["防护动作"]
        Allow["放行工具执行<br/>(产生新结果或有效进展)"]
        Deny["拦截并强制文本回答<br/>(要求智能体总结原因)"]
        Cancel["平滑取消当前会话<br/>(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 一键安装:

dsh plugin --profile web add @goodandready/dsh-agent-loop-guard

重启 DSH 并刷新浏览器工作区。


⚙️ 配置指南

在 config.yaml 或 Web UI 设置面板中配置:

# 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

…(truncated)

Rendered from the README published on npm. Formatted only, not edited.

Versions

Published on npm::20,最后更新 2026-10-20

Links

GitHub · Homepage · npm

Same category