前言¶
DSH 生态里已经有不少插件能告诉你一个目标花了多少钱、多少 token,但这类插件大多到此为止:只读,只展示。长任务真正缺的是下一步——当预算用尽时把目标停下来,而不是让它继续自动续跑。boom-10 维护的 dsh-goal-budget 补的就是这一步:把会话消耗归因到目标,超限后调用官方策略入口阻断目标。下面介绍它实际做了什么,以及怎么装、怎么用。
这是什么¶
一句话定位:给 DSH 的长任务目标设一个 token / 费用(以及计算时间)上限,超了就停,不是只报一个数字。
基本信息来自 README 与 package.json:
- 插件名:dsh-goal-budget
- 维护者:boom-10
- 分类:工作流
- Star:0
- 版本:0.10.2,license MIT
- 运行要求:Node ≥ 22,DSH
>=0.2.1-rc.5 <0.3.0
这个缺口在 DSH 自带代码里被明确承认过。goal-round-driver 的 README 写着:它的轮次上限不是资源预算,token、货币、时间等策略各自独立,会话事件「不会归因到目标消息」「不会被映射成目标的阻断码」。本插件补上三块:按 goalId + round 做归因,给出树内第三个阻断码 budget-exceeded,并在 0.8.0 加入计算时间预算。
核心功能¶
目标维度的归因¶
插件不自己存一份账。它从会话事件日志重建归属关系:agent/inbox/claimed 是唯一把消息和它开启的 turn 配对的事件,assistant/message 携带 turn 和 usage;据此把每个 turn 的消耗累加到对应的 {goalId, round} 上。重启不会重复计费,也不会清零。
阻断而非告警¶
预算超限时,插件调用 ctx.goals.block(),在一次调用里标记目标 blocked 并解除自动续跑。阻断原因是一个稳定的 code 加一段可读说明,例如 budget-exceeded。可选配置 onExceed: block | warn,warn 模式只记日志不阻断。
展示与判定同源¶
输入框状态条里多出一个 pill,点开是花费明细。pill 不自己算钱,读的是与阻断判定同一个投影,因此界面上的数和闸门用的数不会分歧。显示分两种状态:未设上限时面板提示怎么设;设了之后标题栏右侧出现使用百分比,pill 上长出进度条,80% 转琥珀,100% 转红。
计算时间预算¶
除了 token 和费用,还可以设计算时间上限。时长 = 各轮跨度之和(每轮从 turn/start 到最后一个 turn/end),而不是 now - 创建时间,所以目标暂停隔夜不会误爆预算;代价是轮间的空闲不计入。时间只用 SessionEvent.time,不用 Date.now(),重放同一份日志得到同一个数。它是 0.8.0 加入的,pill 上暂时不显示时间。
安装与启用¶
安装命令来自 README 原文,两条等价,按你的 registry 选:
dsh plugin --profile desktop add dsh-goal-budget # npm 源
dsh plugin --profile desktop add github:boom-10/dsh-goal-budget # GitHub 源
装完重启 DSH(客户端和宿主半边都在启动时加载)。两点注意:
- 如果本机默认 registry 是公司内网代理且还没同步到这个包,
add dsh-goal-budget会报ERR_PNPM_NO_VERSIONS,改用 GitHub 源即可。 - 带版本号的形式在两种源上都不可用,不要写
...@0.10.0。
在开放插件市场里搜 Goal Budget 也可以装(已收录)。不配任何预算也能装——插件加载后空转,等你用 /budget 设值。
配置与用法¶
会话内设上限¶
直接在输入框打命令,不改 YAML、不重启:
/budget 查看当前生效的上限和已用量
/budget $5 本会话费用上限 5 美元
/budget 500k 本会话 token 上限 50 万
/budget $5 500k 两个都设,谁先到算谁
/budget $5 30min 费用和计算时间都设,支持 s / min / h
/budget off 清掉会话覆盖,回到 profile 默认
时间单位用 min 而不是 m,因为 m 已被用来表示百万 token。预算按「会话覆盖 ?? profile 默认」解析:固定额度写在配置里,临时收紧在输入框打一行。
profile 默认¶
给所有会话一个固定额度的 YAML 配置如下,字段带注释:
- id: dsh-goal-budget
config:
budget:
tokens: 2000000
costUsd: 5.00
onExceed: block # 或 'warn',只记日志不阻断
warnAtRatio: 0.8
currency: auto # auto:用 DeepSeek 余额接口识别(官方线路);网关线路写 USD 或 CNY
deepseekCredentialRef: DEEPSEEK_API_KEY # 凭据服务里的 Key 引用名
modelAliases: {} # 网关给模型改名时映射,例如 cm-ais/deepseek-v5-flash: deepseek-flash
peakPricing: false # 官方线路 true;网关按固定单价计费时 false(否则高峰时段高估一倍)
两层界面的设计理由是:预算是运行时决策,插件配置是启动时读的部署决策;把预算只放在配置里,改一个临时值就得改 YAML 加重启。会话级预算配会话级界面,就是 /budget 存在的原因。
与其他用量插件的区别¶
生态里报花费的插件已经饱和,且全是只读的,例如 @kenz1117/dsh-ui-usage-billing(账单看板,95 星)、dsh-credits(跟踪余额与套餐)、dsh-composer-balance(显示余额)。它们回答「我花了多少」。本插件回答「该不该继续」,并把这个答案执行下去。
适用场景与注意¶
适合需要给长任务目标加硬预算、不希望烧穿额度自行停止的用户,尤其是配置了目标自动续跑的场景。README 也列出了已知失败模式,需要按预期理解:一轮里若混入人类消息和目标消息,人类的消费可能被记到目标上导致过早阻断,缓解办法是严格过滤 source.kind === 'goal'。
插件以当前 DSH 进程的权限运行,会在你启动的会话里读取事件、注册命令并调用阻断入口。安装前建议先读源码(许可证为 MIT)确认行为符合预期,尤其是计划把它作为部署默认策略时。
结尾¶
dsh-goal-budget 的价值在于把「预算超限」从一个数字变成一个动作:让目标停下,而不是继续烧。它复用 DSH 既有的事件与命令机制,不另起账本,界面与判定共用同一份投影。如果需要更细的归因规则或新增预算维度,建议从源码入手。
- 目录页:https://www.skillhub.cn/plugins/boom-10/dsh-goal-budget
- 源代码:https://github.com/boom-10/dsh-goal-budget