前言¶
在 DeepSeek Harness(DSH)里跑长任务、开 workflow 或扇出子代理时,花费会在短时间内抬升。DSH 核心本身没有「花费上限」或「步数上限」一类硬开关;市场里常见的 cost-meter 类插件,预算多半是展示与变色预警,不会在超支时自动停掉当前回合。下面介绍社区插件 dsh-spend-guard(维护者 summmmerz),它在宿主侧用滚动时间窗口 + 人民币阈值做提醒与熔断,用来弥补「能算钱但不能止血」的空档。
这是什么¶
dsh-spend-guard 是 DSH 的宿主侧插件,分类为 admin-security。当前版本 0.1.1(MIT 许可证,需 Node.js ≥ 20)。它不做独立定价,而是轮询 dsh-cost-meter 的账本,统计「最近 N 分钟」内花了多少(默认 10 分钟),并在达到阈值时:
- 最近 10 分钟内花费达到 ¥1 → 发送 Windows 通知提醒;
- 达到 ¥2 → 结束当前这一轮(与 GUI「停止」按钮同一路径)。
插件在 SkillHub 插件目录 收录;源码与说明见 GitHub:summmmerz/dsh-spend-guard。SkillHub 是社区维护的插件索引站点,与 DeepSeek / 幻方无官方从属关系。
和现有做法差在哪里¶
README 里对生态现状做了对比,要点如下:
- dsh 核心:没有任何花费/步数上限开关。
- dsh-cost-meter 的「预算」:按今日/本月/累计/自定义区间展示;≥80% 预警、≥100% 超支时变色,不会暂停任务。
- 其他预算类插件:例如
dsh-budget是会话/日/月 + USD,peer 范围写死<0.2.0;dsh-balance-tracker以元为单位、动作为取消当前回合,但窗口是自然日,且依赖 dsh 0.2.0 已移除的 0.1.x 客户端包。
dsh-spend-guard 的组合是:滚动分钟窗口 + 金额(元)+ 停当前轮,面向「子代理/workflow 短时间烧穿」这类场景。
核心功能:怎么算「最近 10 分钟花了多少」¶
插件不自己定价,而是轮询差分 cost-meter 账本(默认路径 <DSH_HOME>/storages/cost-meter/ledger.json):
- 每
pollMs(默认 10s)读一次账本; - 对当天聚合值
days[<日期>].cost求相对上次轮询的增量; - 增量按采样时刻写入环形窗口,窗口内求和即为「最近 N 分钟花费」;
- 金额口径跟随账本:
pricingCurrency(默认 USD)× 账本config.exchangeRate(默认 7.2)= 人民币元,与 dsh-cost-meter 界面数字同源。
field 可选 cost(含订阅折算)或 apiCost(纯 API 口径)。
为什么不用 per-session 明细¶
账本里 days[日期].sessions[] 是「每个会话当天的累计值」,在重负载日会截断。README 记录:2026-10-04 实测该数组只保留 200 条、仅覆盖当天 42% 的花费(33.95 / 81.17 元),缺口 47.2 元来自子代理——正是熔断最该拦住的消耗。当天聚合值在任意负载下是完整口径(含子代理),因此插件只信聚合差分。test/window.test.mjs 中有回归测试:sessions 为空或条目被替换/截断时,窗口仍须正确计数。
检测延迟:最多约 pollMs + cost-meter 落盘间隔(默认各 10s),对 10 分钟窗口熔断通常可接受。
降级:账本读不到(未装 cost-meter、格式变动、权限问题)时不熔断,仅每 5 分钟打一条警告日志——算不出钱时不应拖垮 harness。
核心功能:熔断时怎么停¶
停止当前回合调用:
agent.cancel({ kind: 'user' }, { keepInbox: true })
与 GUI「停止」一致(README 指向 dsh-api-session-controller 的 stop 实现):只结束当前回合,不销毁会话,已排队的输入保留。
默认 cancelScope: all 会结束所有正在运行的 agent(含子代理)——熔断目的是立刻止血。若只希望结束主会话,可设 cancelScope: root。
配置¶
默认值可通过 profile 的 cordis.patch.yml 覆盖(插件包内自带 cordis.patch.yml,见 package.json 的 dsh.bundle.patch):
- id: dsh-spend-guard
config:
windowMs: 600000 # 滚动窗口(ms),默认 10 分钟
warnYuan: 1 # 窗口内达到该金额(元) → 提醒
stopYuan: 2 # 窗口内达到该金额(元) → 结束当前回合
pollMs: 10000 # 账本轮询间隔(ms)
field: cost # cost(含订阅折算) | apiCost(纯 API 口径)
exchangeRate: null # 汇率覆盖;null = 用账本的 config.exchangeRate
warnCooldownMs: 60000 # 两条提醒之间的最小间隔(ms)
stopCooldownMs: 60000 # 两次熔断之间的最小间隔(ms);0 = 超限就一直熔断
cancelScope: all # all=结束所有在跑的 agent(含子代理) | root=只结束主会话
toast: true # 是否发 Windows 通知
debug: false # 每次轮询打印窗口金额
ledgerPath: "" # 账本路径;留空=自动定位
整插件禁用:
- id: dsh-spend-guard
disabled: true
启用后,日志里会出现类似一行(路径以本机为准):
[dsh-spend-guard] 已启用: 滚动 10 分钟, 提醒 ¥1.00 / 熔断 ¥2.00, 账本 <path>
提醒与熔断分别带 提醒: / 熔断: 前缀,便于 grep。
安装与启用¶
README 未给出单独的 dsh plugin add … 安装命令。可按社区习惯从 SkillHub 目录页 或 GitHub 仓库 获取插件包,并按 DSH 的 Cordis 插件/bundle 方式装入 profile。
前提:本机需已安装并运行 dsh-cost-meter,且账本持续落盘;否则插件只记警告、不熔断。
安装前建议自行阅读源码与 MIT 许可证:插件以当前 DSH 进程权限运行,会读取账本并在超阈值时调用 agent.cancel。
典型用法与自测¶
日常无需额外操作:装好插件、保证 cost-meter 在跑,即按默认 10 分钟 / ¥1 提醒 / ¥2 熔断 工作。若要改阈值或只熔断主会话,改上一节的 cordis.patch.yml 即可。
仓库自带窗口逻辑测试:
node test/window.test.mjs
或用 npm script:
npm test
测试覆盖:首次轮询建基线、按当天聚合增量计数、1 元提醒 / 2 元熔断、sessions[] 为空或截断时的回归、跨日不误熔断、聚合回退不作负增量、cancelScope 语义,以及熔断须走 cancel({ kind: 'user' }, { keepInbox: true })。
适用场景与已知边界¶
适合:本地长期开 DSH、容易触发 workflow/子代理扇出、希望在「最近几分钟」维度上硬停当前回合的开发者。
注意:
- 依赖 dsh-cost-meter;未启用时静默不生效(仅日志)。
- 窗口精度受轮询间隔限制(默认约 10–20s)。
- 只统计 DSH 账本内的花费;其他终端或网页产生的消费不在窗口内。
- 默认熔断会打断所有在跑回合(含子代理);多会话并行且不想被连带中断时,用
cancelScope: root。
结尾¶
dsh-spend-guard 用滚动窗口把 cost-meter 已有账本变成「能提醒、能停轮」的守卫,默认 ¥1 通知 / ¥2 熔断,并刻意用当天聚合差分避免子代理在 sessions[] 截断时被漏计。目录页:https://www.skillhub.cn/plugins/summmmerz/dsh-spend-guard;源码:https://github.com/summmmerz/dsh-spend-guard。