omp packages

pi-death-loop-guard0.1.2

Anti-death-loop guard extension for pi-coding-agent: detects repeated identical tool calls with unchanged results, warns, blocks, and aborts.

tyanyin Published 2 months ago MIT ~447 downloads/mo

Untested on omp

This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.

Did it work for you?

Result

One report per person. A new report replaces your old one.

Reports 0

No reports yet.

Readme

pi-death-loop-guard

English | 中文

Loop-Guard — Pi 的防死循环插件
模型不可能永远循环下去 —— 它会被警告、被拦截、最终被终止。


npm version license GitHub

pi install npm:pi-death-loop-guard


为什么需要

当小模型陷入困境时,它有时会用完全相同的参数反复调用同一个工具 —— 重复读取同一个文件、重复执行同一条命令、重复更新同一个 todo。每一次重复都在消耗 token、污染对话,而结果从未变化。Pi 本身没有内置的循环检测(#6158,closed no-action):agent 循环会一直持续下去。

pi-death-loop-guard 精确识别这种特征 —— 结果无变化的重复相同工具调用 —— 并以分级方式打断:

  1. 警告 — 注入一条 steer 消息,提示模型更换策略或收尾
  2. 拦截 — 拒绝该工具调用;拦截原因成为喂回模型的 error 消息
  3. 终止 — 通过 ctx.abort() 终止整个用户请求

合法行为完全不受影响:参数不同的调用,或参数相同但结果持续变化的调用(轮询),都不是循环。

安装

pi install npm:pi-death-loop-guard

完成。扩展在下次 Pi 启动时自动加载。无需配置 —— 默认值(3 次警告、5 次拦截、3 次拦截后终止)开箱即用。

锁定版本:

pi install npm:pi-death-loop-guard@0.1.0

或从 GitHub 安装:

pi install git:github.com/Tyan66666/pi-death-loop-guard

工作原理

pi-death-loop-guard 监听 tool_call / tool_result 事件并维护一个 streak 计数器。只有三者全部相同才判定为循环:

  1. 工具名相同
  2. 参数指纹相同 — 递归 key 排序后 JSON 序列化,字段顺序无关
  3. 结果指纹相同 — 文本内容流式 SHA-256(图片只算数量,不比内容)

分级干预(默认值):

阶段 触发 动作
警告 连续 3 次相同 注入 steer 消息:"请停止重复,换一种策略或给出最终回答"
拦截 连续 5 次相同(允许 4 次,拦第 5 次) 返回 { block: true, reason };reason 成为模型可见的 error
终止 同一用户请求内被拦 3 次 ctx.abort() 终止请求

关键细节:

  • 跨参数调用永不计数 — 读取不同文件永不触发,即使内容相同。结果对比只作用于重复的同参数调用。
  • 合法轮询安全 — 参数相同但结果变化的调用不推进 streak。
  • 并行批不推进 streak — 单次 LLM 响应内的并行调用不计数,只允许批内最后一个结果与上次串行结果比较。
  • 拦截后同参数重试会被连续拦截(streak 不重置),直到请求被终止或模型更换参数。
  • terminate 需要 pi ≥ 0.84.1(PR #7715),默认关闭(LOOP_GUARD_USE_TERMINATE);旧版本下插件主体可安全运行。

配置

全部通过环境变量配置,无需配置文件。

变量 默认值 说明
LOOP_GUARD_ENABLED true 总开关
LOOP_GUARD_WARN_THRESHOLD 3 连续多少次相同后警告
LOOP_GUARD_BLOCK_THRESHOLD 5 连续多少次相同后拦截(必须 > warn)
LOOP_GUARD_ABORT_THRESHOLD 3 同一用户请求内拦截多少次后 ctx.abort()
LOOP_GUARD_IGNORE_TOOLS (空) 白名单工具(逗号分隔,如 todo,bash)
LOOP_GUARD_IGNORE_ERRORS false 跳过 isError=true 的结果(错误重试不计数)
LOOP_GUARD_USE_TERMINATE false 拦截时附带 terminate: true(需 pi ≥ 0.84.1)

示例:

LOOP_GUARD_WARN_THRESHOLD=5 LOOP_GUARD_BLOCK_THRESHOLD=8 pi

若 warnThreshold >= blockThreshold,插件会自我禁用并记录错误,而不是异常运行。

插件兼容性

pi-death-loop-guard 只拦截 tool_call(用于拦截)和 tool_result(用于结果指纹)。它不触碰 context 事件,因此可以与上下文压缩插件(如 billion-context-pi)及任何其他扩展共存。

一点须知:当多个扩展同时 block 同一个 tool_call 时,pi 按加载顺序采用第一个 { block: true } 结果。如果你运行多个拦截类扩展,先加载的优先。这是 Pi 扩展模型的固有限制,并非 pi-death-loop-guard 特有。

开发

npm install            # typescript / @types/node / tsx(--ignore-scripts)
npm run check          # tsc 类型检查
npm test               # 单元测试(mock ExtensionAPI 驱动,无需真实 pi)

测试覆盖:警告触发、拦截时机(允许 4 次拦第 5 次)、合法轮询不误伤、跨参数重置、abortThreshold 终止、before_agent_start 重置、ignoreErrors、并行批、useTerminate、ignoreTools 白名单、配置不变量。

已知局限

  • 换参数循环(如轮换读取一组文件)检测不到 —— 通常有进展,危害有限。
  • 交错循环(read(A) → bash(cmd) → read(A) → bash(cmd))不在目标范围。
  • 图片只算数量,不比内容 — 两个不同图片 + 相同文本可能误报。

许可证

MIT。