npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@goodandready/dsh-agent-loop-guard

v0.2.14

Published

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

Readme

📦 @goodandready/dsh-agent-loop-guard


⚡ 核心定位与解决痛点

在自主 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 | 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 个自动化单元与集成测试及静态代码检查:

npm test
npm run check

📄 开源许可证