🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

多智能体监工 MyRemme/dsh-loop-guard

DeepSeek Harness
MyRemme31 天前有提交已提供中文文档扫描:未发现敏感能力

实时审阅智能体推理与调用,拦截死循环空转

30/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/1 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add MyRemme/dsh-loop-guard
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · security
装得上吗
实装验证未通过(unknown),装前请到仓库确认最近更新与 issue
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 31 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
⚠︎ 实装验证未通过(unknown · 2026/10/1) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🟢 扫描:未发现敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描未发现敏感能力:最多只发网络请求、读取自身元数据或只读文件,未发现执行命令、文件写入或敏感信息读取。

扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/schemastery@deepseek-ai/cordis@deepseek-ai/dsh-client-ui-primitives
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 实时审阅推理文本
  • 检测死循环与空转
  • 三档拦截落地

多智能体监工:一个独立模型实时审阅推理文本与工具调用,检测死循环 / 空转 / 偷懒,并按 WARN / BLOCK / STOP 三档落地。DSH 宿主插件 + 浏览器设置界面。

README

由 DeepSeek 最新模型翻译生成
dsh-loop-guard 多智能体监工。一个独立模型实时审阅另一个正在工作的智能体的推理文本与工具调用,检测死循环、空转与偷懒,并按 WARN / BLOCK / STOP 三档落地。 宿主侧是 cordis 插件,浏览器侧是设置页里的一行。单包同时声明 dsh.bundle 与 dsh.client。 四层流水线 实现在 lib/layers.js(可独立单测),hook 接线在 lib/index.js。 ① 采集 TraceStore 轨迹 / 证据 / 预算 │ ② 检测 Detector 可插拔规则注册表 │ ③ 仲裁 Arbiter 规则信号 + 可选模型判决 → WARN / BLOCK / STOP │ ④ 干预 Intervener 按档位落地 ① 采集 TraceStore 每个会话一份,记录工具轨迹与观测指纹,三张表都带 LRU 封顶。 观测摘要是这套东西的地基。只比 action + input 的哈希区分不出「有效轮询」和「空转」:同一个命令反复跑,结果在变说明外部状态在推进,结果不变说明卡死了。
展开完整文档(README 剩余 1 节)
dsh-loop-guard

多智能体监工。一个独立模型实时审阅另一个正在工作的智能体的推理文本与工具调用,检测死循环、空转与偷懒,并按 WARN / BLOCK / STOP 三档落地。

宿主侧是 cordis 插件,浏览器侧是设置页里的一行。单包同时声明 dsh.bundle 与 dsh.client。

四层流水线

实现在 lib/layers.js(可独立单测),hook 接线在 lib/index.js。

① 采集 TraceStore 轨迹 / 证据 / 预算 │ ② 检测 Detector 可插拔规则注册表 │ ③ 仲裁 Arbiter 规则信号 + 可选模型判决 → WARN / BLOCK / STOP │ ④ 干预 Intervener 按档位落地

① 采集

TraceStore 每个会话一份,记录工具轨迹与观测指纹,三张表都带 LRU 封顶。

观测摘要是这套东西的地基。只比 action + input 的哈希区分不出「有效轮询」和「空转」:同一个命令反复跑,结果在变说明外部状态在推进,结果不变说明卡死了。所以每次工具调用都会算一个结果指纹,并记录它与上一次的关系:

| 判读 | 含义 |
| 结果与上次完全相同 | 重复调用且无新信息 → 高度疑似空转 |
| 结果在 N 种取值间来回振荡 | 看似每次都在变,取值种类却不增长 → 状态未推进 |
| 结果有变化 | 外部状态在推进 → 合理轮询 |
| 结果为空 | 没有任何产出 |

指纹前先剥离显式易变量(ISO 时间戳、HH:MM:SS、UUID、十六进制、12ms/3s)。只匹配明确的易变量,不做模糊归一——宁可误报「有变化」,也不能把真实变化压成「相同」,后者会制造假阳性阻断。

② 检测

四条规则,声明式注册,单条抛错不影响其它:

| id | 触发 | 档位 |
| stream-loop | 推理/正文的短语级或字符级周期重复 | STOP |
| tool-repeat | 同一工具同一参数被反复调用 | WARN |
| observation-stall | 结果逐字节相同 / 振荡 / 为空 | WARN~STOP |
| step-stall | 连续多步没有新的可验证结果 | WARN |

字符级周期检测逐字符比对,不抽样。抽样步进会跳过模板里唯一变化的那些字符,第32步…第33步… 这种正常推理会被判成死循环——这是最贵的一类假阳性。同时强制最少验证 64 个字符,且报告的重复次数是实际验证跨度内成立的周期数,不由全文长度推断。

③ 仲裁

规则只负责「发现可疑」,不决定惩罚强度。两条原则:

- 结果逐字节相同是确定性证据,不依赖模型也能定罪,直接 BLOCK;一路到 toolBlockAt 还没换路则升 STOP。
- 仅调用次数多但结果一直在变,只 WARN,并把判决权交给模型。假阻断会毁掉真实工作,漏判只多花 token——默认向漏判倾斜。

模型的角色是撤回者而不是加重者:它能否掉规则对合理轮询的误判,但不能凭想象把规则没发现的东西升到 STOP。

屡犯升级:第 2 次至少 BLOCK,第 3 次 STOP。

④ 干预

| 档位 | 落地方式 |
| WARN | additionalContexts 软提示,不打断 |
| BLOCK | PostToolDecision.block,本次工具调用判失败 |
| STOP | 截断输出流 + agent.steer 把工人抽回来 |

干预带回合归属。监工最长要 timeoutMs(默认 60s)才返回,而收工点最多等 stopWaitMs(默认 8s),判决晚归是常态;没有回合归属,上一个回合的诊断就会被注入到下一个回合。

到 maxStrikes 后插件放手,让回合自然收尾,不再强制续跑。

配置

cordis.patch.yml:

- id: dsh-loop-guard
name: dsh-loop-guard
config:
enabled: true
supervisor:
enabled: true
provider: commandcode
model: zai-org/GLM-5.3
temperature: 0
timeoutMs: 60000
detect:
reasoningLoop: true
textLoop: true
minRepeats: 4
hardAfterHits: 2
toolRepeatThreshold: 3
toolBlockAt: 5
stepStallThreshold: 30
punish:
cutStream: true
blockRepeatTool: true
steerOnStop: true
maxStrikes: 3
budget:
cooldownMs: 20000
maxConsultsPerTurn: 3
maxConsultsPerSession: 40

顶层扁平别名

以下几个旋钮同时提供顶层写法:

toolRepeatThreshold: 3
toolBlockAt: 5
stepStallThreshold: 30
hardAfterHits: 2
cutStream: true
blockRepeatTool: true

顶层优先于嵌套值。这不是冗余:浏览器的设置表单(dsh-client-ui-primitives 的 SettingsFormModel)写操作是 {op:"set", path:[field]}——单段路径,读也是平面取值,嵌套的 detect. / punish. 它既读不出也写不进。UI 改的就是这一层,手改 cordis.patch.yml 两种写法都生效。

监工必须走另一条路由:换了工人的模型,supervisor.provider / supervisor.model 也要跟着换。两个模型相同会让监工调用自己触发自己。

设置界面

设置 → 通用 → 空转监工。可改上面那六个顶层字段,改动即时写回宿主配置。
实现见 lib/client.js:

- 入口是 window.__ModuleLoader__.load({id, factory})
- 注册进 settings.general.item 槽位
- 配置经 ctx.get("configForms").get("dsh-loop-guard") 拿到
- 无条件注册,不用 whileServed 门控:非 loopback 页面下设置文档是进程内的,describe 镜像永远不加载,门控会让这一行根本不存在——看起来像被删了而不是被禁用

两个必须同时满足的条件

一、字段要标 .volatile()。 只有 volatile 字段才会被 harness 生成可编辑的设置表单,dsh-settings 的 hasConfigEntry 也就认不到这个命名空间,浏览器侧只会拿到 status: "unavailable"。schemastery 的校验器还要求 volatile 字段有固定对象路径、且不被外层 volatile 包住——所以标在叶子上,不要标在 supervisor / detect / punish 这些对象上。

二、宿主侧必须拆包。 标了 .volatile() 的字段,cordis 交给插件的是带 .get() 的包装值,而手写在 cordis.patch.yml 补丁行里的则是普通 JSON。normalizeConfig 里走 unwrap() 同时接受两种:

Schema.resolve({ toolRepeatThreshold: 7 }, Config)[0].toolRepeatThreshold
// → { get: [Function], [Symbol(cosmokit.volatile.write)]: [Function] }

不拆包的后果是静默的:typeof wrapper === "object",所有类型判定落空,配置一声不响地退回默认值。

改完立即生效,不用重启

normalizeConfig 里对这几个 volatile 旋钮不取快照,挂的是取值器。

cordis 处理设置写入时,只在 volatile 路径上跑 _commitVolatile(),对包装对象做 targetSymbol.for("cosmokit.volatile.write")——原地改写,并且不会重新执行 apply(dsh-util-values 的 updateVolatile 就是这个实现)。所以插件必须持有包装对象、在用的时候调 .get()。

早先这里把值拷进普通快照对象,UI 改完写进了包装对象而插件再也不看它——于是每调一次参数都要重启。现在改成取值器后,设置界面里的改动立即生效。

需要重启的只剩代码变更(lib/*.js 的逻辑),因为那要求 cordis 重新 import 模块,这一点无法绕过。

读生效值

宿主侧顶层优先于嵌套,但用户的 cordis.patch.yml 里写的是嵌套值、顶层字段压根没被设过。所以这一行读的是生效值(顶层 → 嵌套 → 默认),写一律写到顶层。只读顶层会让 UI 显示 schema 默认值,而插件实际用的是嵌套值。

安装

包自带 dsh.bundle.patch,走 bundle 声明挂载。profile 的 package.json:

{
"dependencies": {
"dsh-loop-guard": "file:./node_modules/dsh-loop-guard"
},
"dsh": {
"profile": {
"bundles": ["…", "dsh-loop-guard"]
}
}
}

cordis.patch.yml 里覆盖 config。改完需要重启 DSH才会重新装载。

测试

仓库外有一组独立探针(不进包),覆盖观测摘要、四层内核、hook 接线、真实加载、真实会话重放:

| 探针 | 覆盖 |
| lg-obs | 观测指纹与易变量剥离 |
| lg-layers | 四层内核:采集/检测/仲裁/干预 |
| lg-integration | 驱动 apply() 注册的四个 hook,走完整调用链 |
| lg-load | 用真的 schemastery 校验 Config |
| lg-ui-config | 顶层别名优先级与向后兼容 |

已知边界

- supervisor 答非所问与调不通走同一条兜底路径。模型回散文而非 JSON 时判决无法解析,插件按「监工不可用」处理并沿用兜底判决;按设计兜底会把规则 WARN 升级到 BLOCK。现在这种情形会打一条 warn 日志,不再静默。
- 规则是哨兵,不是法官。所有阈值都偏保守,宁可漏判。
- 流式检测看的是窗口。windowChars 之外的重复不会被发现。

License

Apache-2.0
预览分享卡片长什么样 ↓MyRemme/dsh-loop-guard
分享 · DeepSeek Harness Hub
MyRemme/dsh-loop-guard

实时审阅智能体推理与调用,拦截死循环空转

回到顶部