dsh-dupguard
同一字符串连续重复达到阈值(默认 10 次)时截停本次生成,已生成内容照常提交;截停后弹出通知,显示所属工作区、会话名称与重复的字符串。重复次数可按单元长度用分段表或 JS 模块决定,代码区域(围栏 / 行内 / 缩进)使用放宽的阈值。
安装
dsh plugin --profile web add dsh-dupguard
沙箱测试结果
| 阶段 | 结果 |
|---|---|
| 1 安装 | ✓ |
| 2 列装 | ✓ |
| 3 挂载 | ✓ |
| 4 启动 | — |
四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。
README
dupguard · DSH 大模型重复输出守卫
[English](README.en.md)







dupguard 是 DeepSeek Harness (DSH) 的实时重复输出守卫插件:最新输出中同一字符串连续重复 10 次及以上(可配置)时弹出决策卡片(输出继续,可立即截停/允许继续;不操作且达到倍数并过最短反应时间才自动停;无通知通道时直接停止),已生成内容正常提交为助手消息。
<sub>徽章由 npm / GitHub / dsh-plugin.org / dsh.so / awesome-dsh-plugin 各自生成;本插件的版本-兼容矩阵见
[兼容性报告](docs/compatibility-report.md)。问题与建议请提到 GitHub Issues。</sub>
如果觉得插件不错的话麻烦点个star谢谢喵~Ciallo~(∠・ω< )⌒☆
截图
截停通知(可选择是否继续) · 被截停的那一轮:输出停在阈值处
 · 
设置页:重复检测(分段表模式) · 设置页:截停与决策
 · 
设置页:通知与日志 · 高级模式(实验性)风险确认
 · 
系统通知(可选,Windows 右下角) ·
 ·
7 张图的展示顺序同时声明在 [screenshots.json](screenshots.json)(供插件市场 / 商店读取);截图中的工作区路径已打码。
第 7 张取自桌面版(Electron),通知署名是应用本身;网页版的通知由浏览器转发,署名是浏览器。
快速开始
前置要求:DSH ≥ 0.1.2-rc.1(一条命令安装;宿主 API 下限为 ≥ 0.1.1-rc.1)、以及你要装到的
profile 名(下面示例用 web)。
Node 版本跟随 DSH:
- DSH 0.2.2-rc.1 起要求 Node ≥ 24.9(上游强制;旧 Node 需先升级运行时);
- DSH 0.2.1 及更早:Node ≥ 20(不支持 Node 18)。
dsh plugin --profile web add dsh-dupguard # 把 web 换成你的 profile 名
重启 DSH 即生效(宿主代码只在进程启动时加载)。看到这两处就说明装好了:
1. 设置页多出「重复守卫」分节,底部显示 设置通道:ready|构建 1.14.0|自动派生:检测窗口 …;
2. 宿主日志出现 [dupguard] 生效参数:…(判断设置是否真的生效,只认这一行)。
默认值开箱可用:连续重复 ≥ 10 次即弹出决策卡片(输出继续;无通知通道/关闭决策时直接截停;已生成内容照常提交为助手消息),思考文本一并检测,代码区域
(围栏代码块、行内代码、缩进代码块三类统一)内按 4 倍放宽。想调整就在设置页改——改完无需重启
(写回 cordis.patch.yml,宿主自行热读取)。
桌面版(Electron):请在应用内「设置 → 插件」页面安装(desktop profile 由应用独占管理,CLI 会被拒绝)。
卸载 / 升级:dsh plugin --profile web remove|update dsh-dupguard;其它安装方式(本地仓库--patch挂载 /
动态插件 / 手工补丁层 / 临时禁用)见 [备选安装方式](#备选安装方式)。
兼容性
项目 · 支持范围
宿主 API · ≥ 0.1.1-rc.1(package.json 的 dsh.compatibility 声明值);一条命令 bundle 安装需 ≥ 0.1.2-rc.1
已实测通过(仓库内有记录) · DSH 0.2.2-rc.1(CLI / web profile,2026-11-05 复核;1.13.3 起已修复 Config 回填)、DSH 0.2.1-rc.2(CLI / web profile 与桌面版,2026-10-20 复核)、DSH 0.2.1-rc.1(CLI / web profile,2026-10-17 复核)、DSH 0.2.0-rc.2(CLI / web profile 与桌面版)(见 [兼容性报告](docs/compatibility-report.md));0.1.7-rc.2、0.1.7-rc.1、0.1.2-rc.1、0.1.1-rc.1(见 CHANGELOG 对应条目)
早期版本(未在本仓库留档) · 0.1.5-rc.2、0.1.6-alpha.2 曾在使用中验证过,但仓库内没有当时的记录,故不计入上方清单
Node · DSH 0.2.2-rc.1+:≥ 24.9(上游强制);DSH ≤ 0.2.1:≥ 20(不支持 Node 18)。.mjs 高级模块依赖运行时的 require(ESM) 支持(Node ≥ 20.19 / ≥ 22.12 已内置;Node 24 自然满足);插件自身代码仍保持 Node ≥ 20 的兼容性
设置命名空间 · 0.1.7 起 = loader entry id(本 bundle 为 include:dupguard);≤ 0.1.6 为 dsh-dupguard。1.6.0 起运行时自动选路,无需按 DSH 版本换插件版本
升级提示 · 0.1.7 起设置键从 dsh-dupguard: 变为 dupguard:,升级后请在设置页重新保存一次(或把旧键内容手工挪到新键下);0.2.2-rc.1 起升级 DSH 前先把 Node 升到 ≥ 24.9
- 结论:检测/截停 API 在 0.2.x 稳定;但 DSH 0.2.2-rc.1 起要求 Node ≥ 24.9,且其 loader 在创建 runtime 时只读一次
Config
(启动期 schemastery 竞态会让设置命名空间缺失,该修复已随 1.13.3 发布;1.13.2 及更早只能重启尝试避开竞态,刷新页面无效)。
桌面版与 CLI 同版本,上述 API 结论适用。
- 旧版本配置直接沿用:配置键自 1.0.0 起只增不减、从未改名(1.0.0 七项 → 1.0.2
ignoredChars→ 1.4.0
skipCodeBlocks/codeBlockMultiplier → 1.7.0 ignoredSubstrings → 1.8.0 thresholdMode/thresholdByLength/
advancedThresholdFile),取值范围只放宽过(codeBlockMultiplier 由 1–100 放宽到 0–100,其余自 1.3.0 起未变),
缺失的键一律取默认值;配置里出现当前 schema 未声明的键(如 fixStandingMountConflict、拼写错误)会被忽略
而不是让整节设置失效 ⇒ 当年通过设置页保存的配置,升级后行为不变(回归用例 S23 覆盖:键只增不减 +
取值范围只放宽)。
- 客户端设置分节的静态依赖只有
slots/locale,设置服务用ctx.inject()动态接入 ⇒ **在已适配的三种设置
模型下**(settings.register、settingsScope、typert remote.settings)不会让入口卡在 pending;DSH 若引入
第四种模型仍需适配。
- 每次核对的证据清单与历史记录(含可直接复制到 DSH Discussions 的报告):
[docs/compatibility-report.md](docs/compatibility-report.md)。
特性
- 逐增量检测:每个
text-delta到达即判定(增量可能含多个 token),命中阈值即进入决策卡片(默认;无通知通道或关闭决策时直接停止)。 - 停止方式:提前结束流 → 上游
iterator.return()→ 适配器finally中consumer.abort()中止底层 HTTP 请求
(远端何时停止由服务端行为决定);不 abort() agent 步骤信号,并补发协议合规的 block-end +
finish(stop),已生成内容正常提交为助手消息,不污染会话日志。
- 多种复读形态:单字符、词语、带空格 / 换行分隔、逐行、前缀后循环(默认去空白后检测)。
- 思考守卫:默认同时检测 reasoning(思考)文本,思考中的复读同样截停(
monitorReasoning: false可关)。 - 图形化设置页(npm 常驻版):与「通用设置 / 模型 / 插件 / Agent 预设」并列的「重复守卫」分节,可视化编辑
白名单与全部检测参数,改完即时生效并持久化。顶部按使用场景分为 3 个分页(布局类似 dsh-cost-meter 的设置页):
分页 · 内容
重复检测 · 模式(简单 / 分段表 / 高级)+ 该模式的次数来源(阈值 / 三列表格 / 模块路径)+ 代码区域内阈值倍数;最小 / 最大重复单元长度;忽略空白 / 检测思考 / 检测工具参数;忽略白名单
截停与决策 · 阈值决策卡片开关 + 暂停显示开关 + 最短反应时间 + 自动截停倍数 + 本地模型不强制截停开关 + 本地 provider 列表
通知与日志 · 截停通知开关 + 系统通知开关(可选,含测试按钮)+ 继续指令内容 + 「记录截停/允许继续日志」开关 + 完整内容开关 + 最近截停/允许继续记录(只读)
- 截停通知 + 一键继续(npm 常驻版):每次截停都会弹出全局通知——与用户当前打开哪个会话无关,
通知上显示所属工作区、会话名称、重复的字符串、重复次数与命中通道;由用户选择是否「发送继续指令」
(注入到被截停的会话)或「不发送」。详见[截停通知与继续指令](#截停通知与继续指令)。
- 可选系统通知(npm 常驻版,默认关闭):打开后,页面不在前台时(标签页在后台、窗口最小化,或窗口失焦)被截停会额外发一条
…(truncated)
以上内容来自 npm 上的 README,我们只做格式化,不改内容。
版本
npm 上共发布:40,最后更新 2026-11-06