dsh-offpeak-guard:给 DeepSeek Harness 加上峰谷计价错峰调度

前言

用 DeepSeek 跑长时间任务时,账单上最大的变量不是模型,是时间段。工作日 09:00–12:00、14:00–18:00 是原价,周末和法定节假日全天是谷价。人工盯着点去掐表暂停,既不现实也容易漏;写脚本定时 kill 会话,又会丢掉待处理队列。DSH 的插件机制允许在会话控制器层面做这件事,下面介绍的 dsh-offpeak-guard 就是这个方向的插件:它读 DeepSeek 的峰谷规则和当前会话的真实模型,在峰时暂停任务、在谷时自动恢复,并把「12 点再跑」这类需求排进下一个谷价窗口。

这是什么

dsh-offpeak-guard 由 HATO-24 维护,分类属于 DSH 社区目录里的「工作流」,许可证为 MIT,npm 上对应包名就是 dsh-offpeak-guard。它不替换 DSH 的任务系统,而是在会话层做一层价格窗口调度:识别当前是峰还是谷,决定正在跑和即将开始的任务该不该放行。

核心思路是两条正交的判断:

  1. 时间:按 DeepSeek 官方规则判断峰谷窗口,含法定节假日处理;
  2. 模型:按会话真实的 provider / model 判断是不是峰谷计价模型,避免误伤不相关的模型。

两者都命中时才介入;其余情况插件不动作。

核心功能

时间识别

按 DeepSeek 官方规则,北京时间周一至周五(不含中国法定节假日)09:00–12:00、14:00–18:00 为峰值原价,其余时间(含周末、法定节假日全天)为谷价,按 5 折计费。节假日默认从公开 API 动态同步,失败时回退内置的 2026 列表。

模型识别

插件按会话的真实 provider / model 精确判断。默认情况下模型名(或供应商名)包含 deepseek 就纳入管理;也可以在设置面板逐模型开关,或用 peakPricedModels / exemptModels 精确控制,这两个列表非空时优先于 modelPattern。

峰时策略与会话豁免

  • 策略可选「立即暂停」或「完成当前轮后暂停」;
  • 会话有子代理在跑时先放行子代理,子代理结束后再暂停父会话,谷价开始时恢复;
  • 可以豁免某个会话不参与暂停/恢复,通过设置面板或 offpeak_guard exempt/unexempt,随时可取消。

工作规划

  • 峰时开始 → 暂停正在运行的任务,保留待处理队列,不丢消息;
  • 峰时新起的任务 → 立即停住,不花峰时 token;
  • 谷价开始 → 自动把被打断的任务交还给会话继续执行;
  • 提供 offpeak_plan 工具,把「12 点再跑」这类事排进下一个谷价窗口。

界面

输入框下方有一条状态条,显示当前峰/谷、距下次切换的倒计时、当前模型,以及暂停/规划数量。左侧栏底部另有一枚常驻计时,临近切换时闪色提醒:峰价快开始闪红,谷价快开始闪绿。点击左栏计时打开设置面板,可以切换峰时策略、逐模型管理、会话豁免、查看节假日同步状态。

另外支持就地豁免:鼠标移到左侧会话行,行尾出现盾牌按钮,点一下豁免或取消;输入框状态条右侧也有「豁免本会话」按钮。

安装与启用

插件已发布到 npm。在 DSH 的插件页搜索 dsh-offpeak-guard 安装,或用命令行:

dsh plugin --profile <profile> add dsh-offpeak-guard

安装完成后建议先看一次 offpeak_status,确认识别到的时段和模型符合预期。

环境要求(来自 package.json 的 engines):

{ "node": ">=22.5", "dsh": ">=0.2.1-rc.2 <0.3.0" }

典型用法

插件提供三个工具,覆盖查询、规划、手动控制。

工具 用途
offpeak_status 当前时段、下次切换、当前模型是否适用、暂停与规划清单
offpeak_plan add / list / remove / clear 错峰规划
offpeak_guard status / pause_now / resume_now / run_plans_now 手动控制

典型的工作流是:

1、长任务在跑,先看 offpeak_status,确认现在是谷价、距峰时还有多久,判断要不要让它继续;
2、如果即将进入峰时,新任务先不要发,用 offpeak_plan add 排进下一个谷价窗口;
3、峰时开始后,插件按设置的策略暂停正在跑的任务,状态条和暂停数量会更新;
4、谷价开始,任务自动交还会话继续跑,offpeak_status 里可以看到恢复记录;
5、遇到必须马上跑的情况,用 offpeak_guard pause_now / resume_now 手动介入,resume_now 会给这些会话 10 分钟豁免,避免刚恢复又被停回去。

配置

配置可以写在 cordis.patch.yml 里 offpeak-guard 那一行的 config,也可以在 DSH 设置页的插件配置里修改(插件已声明 Config schema)。常用键如下,默认值按 package.json 声明。

config:
  enabled: true
  preset: auto
  pauseMode: pause-now
  timezone: Asia/Shanghai
  modelPattern: deepseek
  peakPricedModels: []
  exemptModels: []
  pauseRunningOnPeak: true
  deferNewTurnsOnPeak: true
  resumeOnOffPeak: true
  pollSeconds: 15
  resumeDelaySeconds: 3
  bypassMinutes: 10
  alertMinutes: 10

各键含义:

  • enabled:总开关;
  • preset:auto 按 provider 自动选,WorkBuddy/CodeBuddy 用 workbuddy,其余用 deepseek-official;也可固定为 deepseek-official / workbuddy / custom;
  • pauseMode:pause-now 峰时立即暂停,finish-turn 当前轮跑完再暂停;
  • timezone:计价时区,默认 Asia/Shanghai;
  • peakWeekdays / peakWindows / discount:仅 custom 预设使用,官方调价或换供应商时改这里;
  • holidays:追加的法定节假日,YYYY-MM-DD;
  • holidaySource:auto 动态同步,builtin 只用内置/配置列表;
  • modelPattern / peakPricedModels / exemptModels:模型匹配与豁免;
  • pauseRunningOnPeak / deferNewTurnsOnPeak / resumeOnOffPeak:三条主策略开关;
  • pollSeconds:检查间隔,范围 5–300;
  • resumeDelaySeconds:谷价开始后等几秒再恢复;
  • bypassMinutes:手动恢复后的豁免期;
  • alertMinutes:左栏计时在距切换多少分钟内开始闪烁,0 表示不闪。

环境变量

部署方可以用环境变量统一注入配置,优先级是环境变量 > 配置 > 默认,无效值会被忽略。命名规则统一为 DSH_OFFPEAK_ 前缀加配置键的大写下划线形式,例如:

DSH_OFFPEAK_PRESET=custom
DSH_OFFPEAK_PAUSE_MODE=finish-turn
DSH_OFFPEAK_PEAK_WINDOWS=09:00-12:00,14:00-18:00
DSH_OFFPEAK_DISCOUNT=0.5
DSH_OFFPEAK_HOLIDAYS=2026-10-01,2026-10-02
DSH_OFFPEAK_MODEL_PATTERN=deepseek
DSH_OFFPEAK_PEAK_MODELS=deepseek-flash,vendor/model
DSH_OFFPEAK_BYPASS_MINUTES=10

完整列表见 README,覆盖 enabled、timezone、peakWeekdays、holidaySource、holidayApi、pollSeconds 等全部配置项。

预设

  • deepseek-official(默认):官方工作日峰时 + 内置 2026 法定节假日,节假日全天谷价;
  • workbuddy:WorkBuddy 积分规则,峰时窗口与官方相同,按 provider 自动选择时用于标注来源;
  • custom:完全使用 peakWeekdays / peakWindows / discount / holidays,适合其他供应商或自建计价。

数据与恢复机制

状态和快照都在 $DSH_HOME/offpeak-guard/:

  • state.json:暂停/等待中的任务、错峰规划、会话豁免、精确模型规则、峰时策略;
  • status.json:给输入框状态条/设置面板读的只读快照,同时镜像到 ~/.dsh/offpeak-guard/status.json;
  • holidays.json:动态同步的节假日缓存。

插件不写用户工作区。

暂停用的是 sessionController.cancel,只结束当前一轮、保留待处理队列;恢复用的是 sessionController.prompt,向原会话投递一条「继续上次中断处」的指令,冷会话会被自动唤醒。恢复文本会注明中断时间与被暂停的模型,方便在对话里追溯。

子代理与等待

  • 峰时开始时若会话有正在运行的子代理,先放行父会话与子代理;
  • 子代理结束后,父会话按当前策略暂停(记录为 waiting-children),谷价开始后自动恢复;
  • finish-turn 模式下当前轮允许跑完,如果随后又排入了下一轮,下一轮会在峰时被拦下并记录,谷价开始恢复;
  • 当前轮跑完且没有后续轮次时,记录标记为 completed,不会在谷价时无意义地再起一轮。

这点需要留意:插件只在子代理结束时停住父会话,无法在传输层拦截已经进入父会话历史的消息,子代理结果由模型在父会话恢复后继续消费。

适用场景与注意

适合这三类用法:

  1. 跑长任务、批量任务,希望把 token 成本压到谷价窗口的人;
  2. 需要把「某个时间再跑」这类安排交给模型表达,而不是手写 cron 的人;
  3. 团队部署,希望通过环境变量统一注入峰谷策略的运维方。

几点注意:

  • 插件通过 sessionController 干预会话,实际以当前 dsh 进程的权限运行,安装前建议先读一遍源码确认行为符合预期,许可证为 MIT;
  • 内置法定节假日目前覆盖 2026 年,2027 年安排公布前,动态同步补不上时要用 holidays 或 DSH_OFFPEAK_HOLIDAYS 追加,否则节假日会被当作普通工作日;
  • 动态节假日来自第三方公开 API(默认 timor.tech,只发送年份),离线或接口失败时回退 holidays.json 缓存与内置列表,设 holidaySource: builtin 可完全离线;
  • 只处理有工作目录、非子代理的根会话,避免打断子代理导致父会话卡住;
  • 「会话豁免」只影响后续暂停/恢复,不会自动把已经暂停的任务立即恢复,需要时用 resume_now;
  • 插件自身重启时不会主动打断正在跑的任务,之后进入峰时或新起任务仍按规则处理。

结尾

dsh-offpeak-guard 的价值在于把峰谷计价这件事变成会话层的自动策略,而不是靠人记时间或写一次性脚本。它和 DSH 现有的暂停/恢复机制配合,不丢队列、可豁免、可回溯,适合作为日常跑任务时的默认的第一层成本控制。

目录页:https://www.skillhub.cn/plugins/HATO-24/dsh-offpeak-guard

GitHub:https://github.com/HATO-24/dsh-offpeak-guard

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜