dsh-dupguard 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +6 -4
- package/lib/index.js +7 -4
- package/package.json +1 -1
- package/plugin/host.js +7 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
本文件遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),版本号遵循 [SemVer](https://semver.org/lang/zh-CN/)。
|
|
4
4
|
|
|
5
|
+
## [1.0.3] - 2026-08-30
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- 思考(reasoning)复读守卫:`monitorReasoning` 默认改为开启,思考中同一字符串连续重复
|
|
10
|
+
10 次以上即截停;修复开启后暴露的 reasoning 文本双重累积缺陷(`b.text` 与 `feedText`
|
|
11
|
+
各加一次,导致闭合块文本翻倍);新增"关闭开关"变体套件验证 `monitorReasoning: false`
|
|
12
|
+
时仍全量透传。测试套件双入口各 21 项,加变体共 44 项。
|
|
13
|
+
|
|
5
14
|
## [1.0.2] - 2026-08-27
|
|
6
15
|
|
|
7
16
|
### Fixed
|
package/README.md
CHANGED
|
@@ -19,6 +19,7 @@ When triggered, the already-generated text is committed as a normal assistant me
|
|
|
19
19
|
|
|
20
20
|
- **实时检测**:逐 token(`text-delta`)检测,复读出现即停,延迟为单个增量。
|
|
21
21
|
- **多种复读形态**:单字符循环、词语循环、带空格/换行分隔的复读均能识别(默认去空白后检测)。
|
|
22
|
+
- **思考守卫**:默认同时检测 reasoning(思考)文本,思考中的复读同样会被截停(可通过 `monitorReasoning` 关闭)。
|
|
22
23
|
- **真正的服务端停止**:提前关闭流迭代 → 适配器 `consumer.abort()` → 中断 HTTP 连接,模型在服务端停止生成。
|
|
23
24
|
- **安全停止**:绝不 `abort()` agent 步骤信号;补发协议合规的 `block-end` + `finish(stop)`,消息正常提交。
|
|
24
25
|
- **Markdown 表格友好**:默认忽略连字符与竖线(`ignoredChars` 白名单,可配置),表格分隔行与长分隔线不会被误判为复读。
|
|
@@ -106,7 +107,7 @@ Edit the `CONFIG` block at the top of `plugin/host.js` / `lib/index.js` (both en
|
|
|
106
107
|
| `detectionWindow` | `8192` | 检测滚动窗口(字符,去空白后)/ rolling detection window in chars (after whitespace removal) |
|
|
107
108
|
| `stripWhitespace` | `true` | 检测前移除空白/换行,识别带分隔符的复读 / strip whitespace so `"x x x"` and `"x\nx\nx"` are caught |
|
|
108
109
|
| `ignoredChars` | `['-', '\|']` | 检测时忽略的字符白名单:Markdown 表格分隔行(连字符与竖线)不参与重复统计;需更严格检测时置 `[]` / whitelist of characters ignored during detection: Markdown table separators don't count as repetition; set `[]` for stricter detection |
|
|
109
|
-
| `monitorReasoning` | `
|
|
110
|
+
| `monitorReasoning` | `true` | 是否检测思考文本(思考中的复读同样消耗 token,默认截停;只检测可见输出时置 `false`)/ also guard reasoning (thinking) text — on by default; set `false` to guard visible output only |
|
|
110
111
|
| `monitorToolArguments` | `false` | 是否检测工具调用参数 / also guard tool-call JSON args — off by default (base64/JSON repeats are common) |
|
|
111
112
|
| `fixStandingMountConflict` | `true` | DSH ≤ 0.1.1-rc.1 兼容补丁:幂等化 `cordisInspect.register`,修复 preset standing-mount 多代并存冲突 / idempotent `cordisInspect.register` patch for the DSH ≤ 0.1.1-rc.1 standing-mount conflict |
|
|
112
113
|
|
|
@@ -160,11 +161,12 @@ agent-loop commits the partial text as a normal assistant message.
|
|
|
160
161
|
| 带空格复读 / space-separated | `hello hello hello ...` ×10 |
|
|
161
162
|
| 逐行复读 / line repeats | `抱歉,我无法完成。` ×10 行 |
|
|
162
163
|
| 前缀后循环 / loop after prefix | `好的,下面开始回答:` + `循环` ×10 |
|
|
164
|
+
| 思考复读 / reasoning loop | 思考中 `想` ×10(默认截停) |
|
|
163
165
|
|
|
164
166
|
**不会触发 / Won't trigger**:正常文本中的高频词(检测只针对**连续**重复)、重复 9 次及以下、
|
|
165
|
-
|
|
166
|
-
/ high-frequency words in normal prose (consecutive runs only), ≤9 repeats,
|
|
167
|
-
|
|
167
|
+
工具参数(默认关闭)、Markdown 表格分隔行与长分隔线(连字符与竖线在白名单中,默认忽略)。
|
|
168
|
+
/ high-frequency words in normal prose (consecutive runs only), ≤9 repeats, tool args (off by
|
|
169
|
+
default), Markdown table separator rows and horizontal rules (whitelisted by default).
|
|
168
170
|
|
|
169
171
|
---
|
|
170
172
|
|
package/lib/index.js
CHANGED
|
@@ -32,9 +32,10 @@ const CONFIG = {
|
|
|
32
32
|
// (如 "|---|---|"),正常表格输出会大量连续出现,不应视为复读。
|
|
33
33
|
// 默认忽略连字符与竖线;需要更严格的检测时可改为空数组 []。
|
|
34
34
|
ignoredChars: ['-', '|'],
|
|
35
|
-
// 是否同时检测思考(reasoning
|
|
36
|
-
//
|
|
37
|
-
|
|
35
|
+
// 是否同时检测思考(reasoning)文本。默认开启:思考中的复读同样消耗 token,
|
|
36
|
+
// 应立即截停。注意:正常思考中若连续重复同一字符串 10 次以上(如"等等等等"),
|
|
37
|
+
// 也会被截停,属预期行为;需要只检测可见输出时可置为 false。
|
|
38
|
+
monitorReasoning: true,
|
|
38
39
|
// 是否同时检测工具调用参数(JSON 片段)。默认关闭:JSON / base64 中重复字符很常见。
|
|
39
40
|
monitorToolArguments: false,
|
|
40
41
|
// DSH ≤ 0.1.1-rc.1 兼容补丁(默认开启;实测 0.1.1-rc.1 仍未修复):preset 的 standing mount
|
|
@@ -150,10 +151,12 @@ function createStreamGuard(options) {
|
|
|
150
151
|
}
|
|
151
152
|
case 'reasoning-delta': {
|
|
152
153
|
const b = ensure(chunk.index, 'reasoning')
|
|
153
|
-
b.text += chunk.text // 始终累积:停止时需要完整内容闭合块
|
|
154
154
|
if (CONFIG.monitorReasoning) {
|
|
155
|
+
// feedText 内部负责累积完整文本与检测缓冲,这里不得重复 +=
|
|
155
156
|
const hit = feedText(b, chunk.text)
|
|
156
157
|
if (hit !== null) stopped = hit
|
|
158
|
+
} else {
|
|
159
|
+
b.text += chunk.text // 不检测时仍须累积完整内容以便停止时闭合块
|
|
157
160
|
}
|
|
158
161
|
return
|
|
159
162
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-dupguard",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Real-time repetition guard for DeepSeek Harness (DSH): stops model generation when the same string repeats >=10 times in the streamed output. 实时检测 DSH 大模型流式输出中的重复内容,同一字符串重复十次以上立即停止生成。",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh-plugin",
|
package/plugin/host.js
CHANGED
|
@@ -29,9 +29,10 @@ const CONFIG = {
|
|
|
29
29
|
// (如 "|---|---|"),正常表格输出会大量连续出现,不应视为复读。
|
|
30
30
|
// 默认忽略连字符与竖线;需要更严格的检测时可改为空数组 []。
|
|
31
31
|
ignoredChars: ['-', '|'],
|
|
32
|
-
// 是否同时检测思考(reasoning
|
|
33
|
-
//
|
|
34
|
-
|
|
32
|
+
// 是否同时检测思考(reasoning)文本。默认开启:思考中的复读同样消耗 token,
|
|
33
|
+
// 应立即截停。注意:正常思考中若连续重复同一字符串 10 次以上(如"等等等等"),
|
|
34
|
+
// 也会被截停,属预期行为;需要只检测可见输出时可置为 false。
|
|
35
|
+
monitorReasoning: true,
|
|
35
36
|
// 是否同时检测工具调用参数(JSON 片段)。默认关闭:JSON / base64 中重复字符很常见。
|
|
36
37
|
monitorToolArguments: false,
|
|
37
38
|
// DSH ≤ 0.1.1-rc.1 兼容补丁(默认开启;实测 0.1.1-rc.1 仍未修复):preset 的 standing mount
|
|
@@ -147,10 +148,12 @@ function createStreamGuard(options) {
|
|
|
147
148
|
}
|
|
148
149
|
case 'reasoning-delta': {
|
|
149
150
|
const b = ensure(chunk.index, 'reasoning')
|
|
150
|
-
b.text += chunk.text // 始终累积:停止时需要完整内容闭合块
|
|
151
151
|
if (CONFIG.monitorReasoning) {
|
|
152
|
+
// feedText 内部负责累积完整文本与检测缓冲,这里不得重复 +=
|
|
152
153
|
const hit = feedText(b, chunk.text)
|
|
153
154
|
if (hit !== null) stopped = hit
|
|
155
|
+
} else {
|
|
156
|
+
b.text += chunk.text // 不检测时仍须累积完整内容以便停止时闭合块
|
|
154
157
|
}
|
|
155
158
|
return
|
|
156
159
|
}
|