← 返回列表
未验证
给 DeepSeek Harness 自动压缩用的 rapid-refill…
尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/9/24 · 已提供中文文档
DeepSeek Harness 自动压缩的快速重填断路器:停止徒劳的压缩-重填-压缩循环,该循环会在每一步都消耗一次摘要调用,并报告其背后过大的读取或工具输出。
综合分
29.9
GitHub 分
29.9
用户评分
—
★ Stars
0
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add BOWLUNA/dsh-zcode-breaker该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
信任档位:已验证本站已于 0 天前真实安装成功
- 是什么
- dsh 原生插件 · chat
- 装得上吗
- 本站已真实安装成功(非静态推断)
- 安全吗
- 本站尚未对该插件做风险分级(暂未覆盖,不等同于无风险)
- 还在维护吗
- 活跃:最近一次提交在 1 天前
档位由下列信号合成:本站实装验证(真实安装,当前最高到 L4)· 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。下方各区块是它的证据明细。 验证判据与等级说明 →
🟢实装验证通过· 2026/9/25
由本站实装验证器在真实 dsh 环境安装成功,非静态推断。
数据截至 2026/9/25(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-compaction-basic@deepseek-ai/schemastery用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
由 DeepSeek 最新模型翻译生成dsh-zcode-breaker
test
license: MIT
dsh 0.1.5-rc.2 | 0.1.6-alpha.2
node >=22.19
给 DeepSeek Harness 自动压缩用的 rapid-refill 熔断器:拦住「压完立刻又满、于是每一步都再压一次」这个死循环,并告诉用户是哪个过大的读取或工具输出造成的。思路来自 ZCode 的同名实现。
dsh plugin --profile web add dsh-zcode-breaker
Node: 本插件所挂的宿主在 node 20 上装不出来 —— 在 node 20 上 npm install @deepseek-ai/dsh
只装入 10 个包、没有 dsh 可执行文件,而 node 24 上是 488 个。
package.json 目前仍声明 >=20;徽章写的是实测值。
提高声明下限是一件待拍板的事,不在这里悄悄改掉。
从 ZCode 取了什么,又在哪里走得更远
每一行都应该可核对。中间那列指向 ZCode 源码的文件与行号,而且这些引用不是手打上去就信的:控制工作区的 verify-zcode-citations.mjs 会把每一条拿到一份检出里去解析,并把它找到的那一行原文打出来。最后一列给的是你现在就能跑的命令;没有可主张的,就如实写「暂未超过」,不编。
其中两条路径在 2026-09-22 之前是错的:写的是 core/src/compact/turn-loop-state.ts 与 core/src/compact/runtime/methods/compact.ts,那是从一份设计笔记里抄的,不是从源码里核的。真实位置在 packages/core/src/runtime/methods/ 下。守卫抓不到这个错,因为不带行号的路径根本不算它要看的引用 —— 这也正是中间那列现在必须带行号的原因。
| ZCode 有什么 | 本插件取了什么 | 本插件多了什么(优于在哪) | 证据 |
| --- | --- | --- | --- |
| rapid-refill 状态机 —— consecutiveRapidRefills、toolTurnsSinceCompact、shouldBlock,计算在 zcode/apps/zcode-cli/packages/core/src/runtime/methods/turn-loop-state.ts:158 | 同样这三件状态 | 工具轮次是从 DSH 的持久会话日志里读出来的(一条带至少一次工具调用的 assistant 消息),而不是 ZCode 自己 turn loop 里的计数器。这与压缩接缝判断表面平衡时用的是同一个单位 —— 是量出来的,不是猜出来的步数 | node --test test/tracker.test.js —— 「a healthy gap never trips the breaker, however long the run」 |
| 拒绝的判定 —— shouldBlock: consecutiveRapidRefills >= MAX_CONSECUTIVE_RAPID_REFILLS(…/turn-loop-state.ts:165),在 if (context.rapidRefill.shouldBlock) 处被采纳(…/runtime/methods/compact.ts:230) | 同样的拒绝,且在摘要调用之前 | 拒绝会锁定,而且发生在摘要之前而不是之后:模型调用一次都不花,且被跳闸的会话会一直保持跳闸,直到被重新武装 | node --test test/tracker.test.js —— 「the trip happens before the futile compaction, not after it」「once tripped, every later attempt stays refused」 |
| 阈值是模块级常量 —— RAPID_REFILL_TOOL_TURN_THRESHOLD = 3 与 MAX_CONSECUTIVE_RAPID_REFILLS = 3(…/turn-loop-state.ts:21) | 同样两个阈值:toolTurnThreshold 与 maxConsecutiveRapidRefills | 它们是行配置而不是编译期常量,所以 profile 行与 preset 行可以不一样 —— 而且引擎挂载时会把实际拿到的值打出来 | node tools/boot-check.mjs --port 32100 会打出 compaction-breaker armed: rapid below 7 tool turns, trip at 3 in a row —— 那是一个配了 7 的行,默认值不可能产生这个输出 |
| 停机提示是 CLI 打出来的一个字符串 —— Autocompact stopped because the context refilled within fewer than … tool turns(…/runtime/helpers/model-errors.ts:52),并带 reason: "compact_rapid_refill_breaker"(:57) | 熔断期间注入一个 prompt 段,另有 /compaction-breaker status\|reset | DSH 的宿主会吞掉自动压缩路径抛出的错误并继续这一轮。同样一个抛出,会让用户只看到压缩被静默关掉而没有任何解释;注入的提示段才是让「停下」可见的东西 | node --test test/engine.test.js —— 「the trip registers exactly one prompt section」(名字为 compaction-breaker:tripped)、「the /compaction-breaker command reports state and resets on request」 |
| microcompact.ts —— 整条清空旧工具结果、保留最近 5 条(…/packages/core/src/compact/microcompact.ts:14) | 不取 | 暂未超过。 DSH 自带一个不同的确定性 pruner;本插件刻意不重做 ZCode 那套,也不主张在这件事上强过它 | — |
| 熔断挂在 ZCode 自己的 turn loop 上 | 挂在 DSH 的 agent/pre-step 步压力路径上,替换 ctx.compaction 里的一行 | 不依赖外部 CLI 的轮次概念,并且以「单槽位服务的一行替换」接入 | node tools/boot-check.mjs --port 32100 —— 断言 B 是从 cordis.patch.yml 里读行名;docs/MEASUREMENTS.md 记录了真实会话里到达的 trigger=pressure |
怎么自己复核这张表
git clone https://github.com/BOWLUNA/dsh-zcode-breaker && cd dsh-zcode-breaker
npm install --no-audit --no-fund @deepseek-ai/dsh@0.1.6-alpha.2 # 本插件所挂的宿主
node --test test/tracker.test.js # 状态机与拒绝,含跳闸的先后顺序
node --test test/engine.test.js # 包覆层:委派、prompt 段、命令
node tools/boot-check.mjs --port 32100 # 真装真启动(四条断言)
node --test 不需要任何测试运行器,也不需要任何依赖。前两条就是上表的证据列;第三条是本仓库里唯一会真正 apply 插件的一道检查。
它解决的具体问题
@deepseek-ai/dsh-compaction-basic 里自动压缩有两条触发路径:
| 触发 | 入口 | 次数上限 |
| --- | --- | --- |
| 步边界压力 | agent/pre-step 调 compactIfNeeded(agent, "pressure") | 无 |
| 溢出恢复 | agent/request-error 调 compactIfNeeded(agent, "context-overflow") | maxOverflowRetries |
压力那条是无上限的:测得的压力一旦超过 thresholdRatio,下一步就再压一次,而每次压缩都是一次完整的摘要模型调用。于是一次过大的文件读取或工具输出就能造出这样一个循环——每一步烧掉一次模型调用,直到会话被放弃,而转录里只会反复出现下面这一行:
compaction (step pressure): shadowed N surface nodes (seqs A-B, ~T tokens)
它做了什么
它继承 BasicCompactionEngine,只包住一个方法:compactIfNeeded。
- 状态按 session 隔离,多会话互不污染。
- 「工具轮次」取自持久会话日志:一条带至少一个工具调用的助手消息。这与压缩接缝自己判断 surface 配对时用的口径一致,而不是猜的步数。
- 距上次压缩不足 toolTurnThreshold 个工具轮次又需要压缩,记一次 rapid refill。
- 连续达到 maxConsecutiveRapidRefills 次时,在这次压缩真正执行之前就拒绝它,那一发摘要调用永远不会被花掉。
- 拒绝会锁定状态,并抛出携带可操作建议的 CompactionRapidRefillError。
- 熔断期间还会注入一个 prompt 段。因为宿主会吞掉 compactIfNeeded 抛出的错误并继续该轮,只抛错的话用户什么都看不到。
- 命令 /compaction-breaker 用来查看状态并重新武装。
其余全部保留父类行为:触发策略、保留比例、surface 改写、工具配对安全与摘要实现。
两个平面,以及为什么两个都要管
标准 harness 里 compaction-basic 存在两份:一份是 @deepseek-ai/dsh-base 的宿主平面行,另一份在 agent preset 的 compaction 分组里,该分组声明了 isolate: { compaction: true, toolResultPruner: true }。agent 会话的 ctx.compaction 解析到那个隔离域里,而不加入任何 preset 的会话解析到宿主那一行。这就是为什么只打 profile 补丁改变不了 agent 的压缩,也是本节后半段那个 preset 行存在的原因。
这个接缝是单槽位的:同一 isolate 作用域出现第二个 provider 会让 ctx.provide() 抛错,而 ctx.reflect.set() 只接受持有该服务的 fiber 的写入。因此每个平面都靠替换它那一行来覆盖,而不是遮蔽它。
| 平面 | 服务谁 | 本包怎么覆盖它 |
| --- | --- | --- |
| 宿主 | 不加入任何 agent preset 的会话 | 自动,通过安装器挂上的 bundle patch |
| agent 域 | 每一个普通会话 | 在你的 agent preset 里替换一行,因为任何 profile 补丁都够不到一个域 |
支持哪些 harness 版本,以及为什么停在这里
=0.1.5-rc.2 =0.1.6-alpha.1 /.agent-presets/ 里的 preset 会被发现 | 不会 —— 种了 breaker-trip 之后 list() 返回 [] |
0.1.7 把 preset 发现机制换成了声明式注册表(dsh-agent-preset-registry,自述为
"Declarative Agent preset registry and profile-backed editing"),而注册表不扫描目录。
本插件的宿主那一半在 0.1.7 上是好的;但上面那段 README 让你去配的preset 那一半不是。
凭宿主那一半就说「支持 0.1.7」是半句真话,所以区间把它排除了 —— 包括 0.1.7 的正式版,
而一个写成 ... =0.1.5-rc.2 =0.1.6-alpha.1 <0.1.7-0。
用户能看到的面
| 面 | 内容 |
| --- | --- |
| 日志 | 一行 warn,写明连续次数、阈值与上一次间隔 |
| /compaction-breaker | 状态报告;/compaction-breaker reset 重新武装 |
| prompt 段 | 熔断期间注入,指示模型把情况转述给人 |
状态语义——三个刻意的决定
1. 拒绝即锁定。被拒绝的尝试不会 commit,所以若不锁定,间隔一超过阈值就会自动放开,变成「拦两次放一次」。锁定才让它成为停机而不是减速。
2. 只有两条出路:reset 子命令,或一次成功的手动 /compact。人工主动压缩是新信息,不该被自动路径的历史拦住。
3. 重置不清零工具轮次时钟。那是会话的单调时钟,清零会让之后所有间隔都显得健康。被清掉的只有 rapid 计数、上次压缩标记、锁定与拒绝次数。
熔断不是全局禁用:会话照常可用,只是它这一个 session 的自动压缩停了。
兼容性与已知边界
- 它与其它压缩引擎互斥。若干后端都占同一个 ctx.compaction 槽位,它们都无法与本引擎同时挂载。这是接缝本身的限制,不是本插件的选择。
- 宿主平面那一行不受影响,因此不组合 preset 的会话完全不受影响。
- 父类默认值被继承:父类自己的 schema 不带默认值,默认值由它的 resolver 提供。因此父类将来新增的键需要在这里重新声明,才能继续可配。
- 状态放在模块级 WeakMap,而不是类的私有字段。这是刻意的:域交给使用方的那个 ctx.compaction 对象,不保证是私有初始化器跑过的那个,而私有字段读取会在压缩路径里抛错——偏偏那里宿主会把错误吞掉。
- 模型驱动的那一段端到端验收尚未跑过。 直到「引擎在真实域里服务 ctx.compaction」为止的每一步都已验证,详见 docs/MEASUREMENTS.md。
与别的后端组合
策略核心是导出可复用的,别的后端大约二十行就能接入:
import { RapidRefillTracker } from 'dsh-zcode-breaker/tracker';
const tracker = new RapidRefillTracker({ toolTurnThreshold: 2, maxConsecutiveRapidRefills: 3 });
tracker.noteToolTurn();
const gate = tracker.gate();
if (gate.blocked) throw new Error('rapid refill loop');
const result = await myEngine.compact();
if (result !== null) tracker.commitCompaction(gate.projectedConsecutiveRapidRefills);
测试
npm test
19 个测试、2 个测试套件,不需要任何服务、模型或会话:策略核心在 test/tracker.test.js,引擎接线在 test/engine.test.js。接线那套需要 peer 包可解析,解析不到时会跳过而不是失败。
路线图
- 跑模型驱动的验收:在真实会话里造出回填循环,看熔断真的跳闸。
- 支持运行时选择父类,从而与用户偏好的任意后端组合。
- 把策略核心提给上游 @deepseek-ai/dsh-compaction-basic。
许可
MIT