把跑偏的思考块收回思考通道,规则可逐条开关
31.3/100
综合分
3
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/11/3 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add visiter911/dsh-thinking-guard该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
是什么
dsh 原生插件 · other
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 10 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件发起外部网络请求
查看扫描证据(共 8 处,展示前 8 条)
- 读取本地文件index.js:240
raw = await readFile(this.file, 'utf8') - 写入本地文件index.js:264
await mkdir(path.dirname(this.file), { recursive: true }) - 写入本地文件index.js:266
await writeFile(tmp, `${JSON.stringify(state, null, 2)}\n`, 'utf8') - 写入本地文件index.js:267
await rename(tmp, this.file) - 发起网络请求client.js:163
const response = await fetch(`${API}/state?sessionId=${encodeURIComponent(sessionId)}`, { - 发起网络请求client.js:174
const response = await fetch(`${API}/rules`, { - 发起网络请求client.js:226
const response = await fetch(`${API}/provider?providerId=${encodeURIComponent(providerId)}`, { - 发起网络请求client.js:237
const response = await fetch(`${API}/provider`, {
扫描于 2026/11/3(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
DeepSeek Harness 插件:把跑偏的思考块收回思考通道(缝合 / 封装 / 工具调用还原 / 去重 / 开口改写),每一条规则都有独立开关,默认全关、纯透传。
README
由 DeepSeek 最新模型翻译生成dsh-thinking-guard
DeepSeek Harness 插件:把跑偏的思考块收回思考通道。
模型的思考有时会跑到正文里、被拦腰截断、或者把工具调用写成文本标记。这个插件在 llm/stream 上加一层可开关的修复流水线,把内容放回它该在的通道——默认全部关闭,纯透传,你要哪条再打开哪条。
- 顶部 composer 的「规则」面板,按会话独立配置
- 子代理默认继承父会话规则
- 服务商卡片里的「思考块回传」开关(官方 DeepSeek 系默认开,第三方默认关)
- 118 条测试,零网络依赖
快速开始
1. 放进插件目录
git clone https://github.com/visiter911/dsh-thinking-guard.git \
~/.dsh/plugins-src/dsh-thinking-guard
2. profile 里登记(详见 INSTALL.md) profiles/desktop/package.json → dependencies + dsh.profile.bundles
3. 安装并重启 DSH
cd ~/.dsh/profiles/desktop && pnpm install
完整步骤、验证方法与卸载方式见 INSTALL.md。
展开完整文档(README 剩余 1 节)
dsh-thinking-guard
DeepSeek Harness 插件:把跑偏的思考块收回思考通道。
模型的思考有时会跑到正文里、被拦腰截断、或者把工具调用写成文本标记。这个插件在 llm/stream 上加一层可开关的修复流水线,把内容放回它该在的通道——默认全部关闭,纯透传,你要哪条再打开哪条。
- 顶部 composer 的「规则」面板,按会话独立配置
- 子代理默认继承父会话规则
- 服务商卡片里的「思考块回传」开关(官方 DeepSeek 系默认开,第三方默认关)
- 118 条测试,零网络依赖
快速开始
1. 放进插件目录
git clone https://github.com/visiter911/dsh-thinking-guard.git \
~/.dsh/plugins-src/dsh-thinking-guard
2. profile 里登记(详见 INSTALL.md) profiles/desktop/package.json → dependencies + dsh.profile.bundles
3. 安装并重启 DSH
cd ~/.dsh/profiles/desktop && pnpm install
完整步骤、验证方法与卸载方式见 INSTALL.md。
规则一览
| 规则 | 缺省 | 作用 |
| 思考缝合 seamRepair | 关 | 被误判成结束的半截思考,接回同一个思考块 |
| 思考封装 wrapThinking | 关 | 整段写进正文的思考,改判成思考块 |
| 工具调用还原 dsmlSplit | 关 | 正文/思考里的 DSML 标记还原成结构化 tool-call |
| 重复正文去重 dedupeText | 关 | 正文复述思考时丢弃重复部分 |
| 开口改写 letmeRewrite | 关 | Let me X → I'll X,含两个子开关 |
架构
llm/stream 钩子(同步) ↓ 命中开关的转换器按顺序串接 dsml-split → dedupe → wrap → seam → letme ↓ 原样透传未命中的 chunk
每个转换器都是「不命中就原样放行」的纯函数式状态机,块结束时会同步改写 block-end.block.text(它才是一致性的真相来源)。
详细说明
现有规则
| key | 名称 | 缺省 | 作用 |
| seamRepair | 思考缝合 | 开 | 被上游误判成「思考结束」的半截思考,接回同一个思考块 |
| wrapThinking | 思考封装 | 开 | 整段写进正文的思考,缓冲 20 token 后改判成思考块 |
| letmeRewrite | 开口改写 | 关 | 父开关:Let me X → I'll X;展开后有子开关 |
| fillerStrip | 语气词剔除(子) | 开 | Hmm / Uh / 嗯 等句首语气词 |
| intentPrune | 短意图剔除(子) | 开 | 连续意图只保留最后一条完整的 |
子开关只在父项打开时生效;父项关闭时子开关变灰。徽章只统计顶层规则。
思考封装(wrap.js)
现象:模型把思考直接写进了 content 通道,界面上就是一大段「我在想…」的正文。
做法:本轮没有思考块时,正文块先缓冲,不急着决定;等到下一拍看后面跟的是什么。
判据(中间可以折叠,最终正文绝不能被吃):
| 情况 | 结果 |
| 本轮已有思考块 | 不介入(思考块后只可能是正文) |
| 以 # 起手 | 正文,原样放行 |
| 开头像进度汇报(reportScore >= 3) | 正文 |
| 其余情况,块后跟着 tool call | 回合中段的思考 → 折叠 |
| 其余情况,块后直接收尾 | 最终答复 → 保持正文 |
| 缓冲中出现行首 # | 汇报式导语+短前缀 → 整块正文;否则从 # 处切开 |
| 缓冲超过 1500 字符 | 提前定案为思考,避免把长回复一直扣住 |
| 正文里有 <thinking>…</thinking> | 标记内部一律归思考(这条不受「已有思考块」限制) |
「延迟一拍」是这条规则的核心:块结束时先扣住内容,等下一个 chunk——是 tool call 就说明这只是中段思考,否则说明这就是最终答复。
切开时正文块需要一个新的 index(原文块已被改判成思考),用 1_000_000 + 原 index 占位,避开真实序号。代价:该消息的 replayState 块数对不上,replay 元数据会退化(assistant 消息仍能正常回放,只是走兜底路径)。
空块不封装,避免造出空思考块。
代价:不以 # 开头、且本轮没有思考块的回答会被移进思考面板。觉得太激进可以按会话关掉这条规则。
处理顺序
模型流 → 去重 → 封装 → 缝合 → 开口改写 → 输出
顺序不能换:
- 去重必须最先:否则封装会先把重复块切开,去重就认不出「逐字节相同」了
- 封装在中:它的采样要看到原始文本,不能被缝合的缓冲截断
- 缝合:处理封装之后仍然存在的接缝
- 开口改写最后:它只动思考文本;前面若还有结构问题,改写的内容会被块的收尾文本覆盖
开口改写(letme.js)
只处理思考通道,正文一个字都不碰。按句子缓冲(句末标点或 400 字符),攒够一句就改写并发出,不做整块延迟。
- Let me X → I'll / I will / I'm going to / I should / I need to / Now I'll(单数第一人称)
- Let's X → We'll / We should / We need to / We're going to(复数,语义不同不混用)
- 让我 X → 我来 / 我先 / 我得 / 我需要 / 接下来我
- 按句子内容哈希选句式:同一句永远同一个结果,整段自然分散,不会全塌成一句
- 只改开口(英文前 8 字符、中文前 6 字符),句中的 let me 不动
- block-end 的 text 写成改写后的累积文本,否则会被原始文本覆盖
语气词剔除
句首含义为零的语气词直接删掉,删完把露出来的首字母大写:
| 语言 | 剔除 |
| 英文 | Hmm Hmmm Hm Uh Uhm Um Umm Er Erm Ah Eh |
| 中文 | 嗯 呃 唔 唉 |
- 只削句首:句中的 hmm(比如正在讨论这个词)一个字都不动
- 整块只有语气词时,块收尾文本写成空串,不残留 " "
- 先削语气词再改开口——否则「嗯,让我看看」里的「让我」不在句首,改不到
短意图聚合
以意图开口起头、句子很短(英 ≤60 / 中 ≤30 字符)的句子视为意图句:
- 泛指的直接删:动作部分没有具体对象,如 I'll check it. / 我来看看。
- 连续意图只留最后一条完整的:遇到非意图句或块结束时结算,从后往前找第一条「有具体动作」的,其余剔除
- 非意图句不受影响,顺序不变(先放出攒着的意图,再发当前句)
思考块回传(供应商级)
设置 → 模型 → 供应商卡片里的开关。控制请求历史里 assistant 消息的 reasoning 块是否回传。
- 官方供应商(provider id 以 deepseek 开头):缺省开。服务端要求多轮工具调用携带 reasoning_content,关掉会导致 400。
- 其它供应商:缺省关。
- 任何供应商都可以显式覆盖,覆盖值持久化在 ~/.dsh/thinking-guard.json 的 providers 下。
实现位置:llm/stream 的 options.messages。开关为关时,在调用 next() 之前把 assistant 消息里的 reasoning 块裁掉(整条只剩思考时保持原样,避免产出空消息)。
思考缝合(seam.js)
现象:模型在自己的思考里吐出字面的思考标记(例如 thinking ),服务端的通道分离器把它当成结束标记,于是同一段思考的后半截以 content 字段下发,看起来像一个正文块;后面还可能跟一个字面的 </think>。
判定:只认接缝处的机械断裂,不猜语义。
1. 尾部最后一行有未闭合的反引号 / 括号,正文紧接着闭掉它
2. 拉丁词被从中间劈开
3. 尾部停在逗号 / 分号 / 冒号 / 破折号上
4. 尾部停在连接词上
任一条成立,且正文不是以标题 / 列表 / 答案开场词开头 → 认定是同一段思考。
处置:
- 后续 text delta 继续喂给同一个仍然打开的思考块(原 index)
- 折叠到真正的结束标记为止:</think> 这类 token 是模型自己生成在正确位置上的,标记之前归思考,标记之后恢复为正文(用正文块自己的 index),标记本身消费掉
- 直到块结束都没出现结束标记时:整块并入思考,上游正文块的 block-start / block-end 一起丢掉,不凭空开一个正文块
- 思考块自始至终是一个整块,后面模型真正的思考块照常接得上
判据不成立时逐 chunk 原样放行。
结构
index.js 宿主:RULE_DEFS(唯一事实来源)+ 状态文件 + /dsh-thinking-guard 路由 client.js 客户端:conversation.input.left 胶囊 + 面板壳
状态文件:~/.dsh/thinking-guard.json
{
"version": 1,
"sessions": {
"session-xxxx": { "someRule": true }
}
}
键是 sessionId,所以每个会话一份配置,互不影响;没有条目的会话走 RULE_DEFS 的 default。
子代理继承
subagent 的子会话默认继承父会话的规则:
- 父会话开着的规则,子代理跟着生效
- 父会话显式关掉的规则,子代理也是关的
- 子会话自己写过的键优先(在子会话里单独改过,就以它为准)
- 最多向上追溯 8 层,越界或没有父会话时回落到缺省值
父会话关系来自 session.header:origin === 'subagent' 时取 parentSession。
普通会话(origin 不是 subagent)不继承,直接用自己的配置或缺省值。
路由
| 方法 | 路径 | 用途 |
| GET | /dsh-thinking-guard/state?sessionId=… | 取本会话生效规则 + 规则清单 defs |
| PUT | /dsh-thinking-guard/rules | 写本会话覆盖,body { sessionId, rules: { key: bool } } |
| DELETE | /dsh-thinking-guard/rules?sessionId=… | 抹掉本会话覆盖,回到缺省 |
未知的 key 会被忽略而不是报错,避免旧前端写坏状态。
加一条规则
只改 index.js 的 RULE_DEFS:
export const RULE_DEFS = [
{ key: 'openerRewrite', zh: '开口改写', en: 'Rewrite openers', zhHint: '…', enHint: '…', default: false }, ]
界面、徽章计数、「恢复默认」全部自动跟上 —— 客户端不写死条目。
这也正是上一版出问题的根源:界面和判定各写一份口径,迟早会漂移。
停用
在 profile 的 cordis.patch.yml 加:
- id: thinking-guard
disabled: true
disabled 是加载器级开关,客户端半边也不会加载,胶囊随之消失。
安装
1. 在配置档 package.json 的 dependencies 里加上 "dsh-thinking-guard": "link:../../plugins-src/dsh-thinking-guard"
2. 在 dsh.profile.bundles 里加上 "dsh-thinking-guard"
3. 在配置档目录下运行 pnpm install
4. 重启 DSH预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
visiter911/dsh-thinking-guard
把跑偏的思考块收回思考通道,规则可逐条开关
相关插件 · 其他
模型破甲清洗HunYiSage/dsh-purge
⚔️ DeepSeek Harness 网络安全红队工具dsh-purge
★ 16,993已汉化DeepSeek 客户端
73
女娲蒸馏alchaincyf/nuwa-skill
输入名人名字,提炼其思维模型与决策方式供你调用
★ 37,308已汉化DSH
72
逆向分析桥接Fanqi89/dsh-rea
REA(Reverse Engineer Anything)MCP 桥接,用来把 REA 逆向工具接入 DSH 插件
★ 51已汉化DSH
72
语音女友beiyege-01/dsh-voice-ai-girlfriend
语音 AI 女友Voice AI girlfriend for DeepSeek Harness:Whisper…
★ 888已汉化DSH
71.6
红队越狱测试套件Minglink/dsh-infinite-gen-5
DeepSeek v4.1 flash 逆向工具无限五代 求 Star 收藏 ⭐欢迎大家提交项目的改进
★ 3,759已汉化DSH
71.4
协同办公空间dream-num/univer-workspace
一个让人类与 AI Agent 共同创作、协作和审阅的开源 Office 工作空间。
★ 2,269已汉化DSH
70.8
这是你的仓库?认领条目