dsh-omp-retry:为 DSH 补齐 OMP 式 429 与 thinking 块重试

前言

在 DeepSeek Harness(DSH)里跑长对话或经多通道代理转发时,两类失败经常被内置执行器直接判为终态:上游返回 HTTP 429 限流,以及携带 thinking 块的请求因签名与会话绑定不匹配而被网关以 400 拒绝。DSH 默认对 429 只做最多五次、500 ms 到 10 s 的退避,限流窗口可能尚未过去重试预算就已用完;对 thinking 块绑定错误则归类为 INVALID_REQUEST 且不重试,整轮对话随之结束。Open Multi-Provider(OMP)生态里对上述情况有更耐心的策略。dsh-labs 维护的 dsh-omp-retry 以插件形式把其中与 DSH 相关的两条策略搬进 Harness,无需 fork DSH 本体。

这是什么

dsh-omp-retry 是分类为「工作流」的 DSH 插件,由 dsh-labs 发布,在 SkillHub 插件目录 可查阅条目。它针对两类失败定制重试:HTTP 429 限流,以及正文包含 Invalid signature in thinking block 或 bound to a different conversation 等特征的 thinking 块绑定拒绝。实现上在 dsh-llm-retry 之前挂载 agent/request-error 监听器,仅接管这两种场景;其余错误仍走内置执行器,插件未加载时行为与默认一致。

社区目录 SkillHub 与 DeepSeek、幻方无官方从属关系;安装与运行均在当前 DSH 进程权限下进行,启用前建议浏览 GitHub 仓库 源码与 MIT 许可证。

核心功能

HTTP 429 限流

  • 每个失败步骤最多 10 次限流重试(可配置)。
  • 等待时间为 max(30 s, 上游 Retry-After)。
  • 若必须等待超过 5 分钟,则终止重试链,不再 sleep。
  • 重试预算与 dsh-llm-retry 共用:按解析后的 provider retryPolicy 对应一个持久化策略键。

相较 DSH 默认的五次、亚秒到 10 秒退避,这一策略更贴近 OMP 对 TPM/RPM 窗口的等待方式。

thinking 块绑定拒绝

多上游或轮换会话身份的代理在重放带签名的 thinking 块时,可能返回 400 且文案指向签名或会话不匹配;同一历史再次发送往往能落到接受该块的上游。DSH 若不重试,整轮即失败。

本插件对此类错误:

  • 每个失败步骤最多 5 次重试(可配置),指数退避 500 ms 至 8 s,抖动比例 25%,形状与 provider 本地退避相近。
  • 预算与 provider retryPolicy 独立,即使用户未改 provider 默认策略也会获得绑定重试。
  • 匹配依据为响应正文中的特征字符串,而非失败码,以降低网关改码后的误判。

共用行为

  • 每次计划中的重试会追加持久的 llm/retry、llm/retry-started 事件,常规重试 UI 与会话历史仍可用。
  • 取消、回合结束、插件卸载会中止当前等待。
  • SERVER、TIMEOUT、TRANSPORT、EMPTY_RESPONSE、CONTEXT_WINDOW_EXCEEDED、QUOTA、AUTH 不由本插件重试。

安装与启用

按 README 官方命令安装(将 desktop 换成你实际使用的 profile 名称,例如 Web 或自定义 profile):

dsh plugin --profile desktop add github:dsh-labs/dsh-omp-retry

安装后重启 DSH。插件会通过 bundle 自行插入 omp-rate-limit-retry 配置行,无需手工注册监听器。

README 记载已在 DSH Desktop 0.2.1-rc.5 上验证;依赖 agent/request-error 瀑布流、llm-retry 会话投影(llmRetry)以及内置重试执行器使用的 llm/retry 事件形态。若未来 DSH 变更这些契约,插件可能需要更新;无法处理时会 fail closed,交给下游监听器。

配置

默认值(限流):maxRetries: 10,floorMs: 30000,maxDelayMs: 300000。
默认值(thinking 块):maxRetries: 5,initialDelayMs: 500,maxDelayMs: 8000,jitterRatio: 0.25。

在 profile 的 cordis.patch.yml 中覆盖 omp-rate-limit-retry 行即可:

- id: omp-rate-limit-retry
  config:
    maxRetries: 10
    floorMs: 30000
    maxDelayMs: 300000
    thinkingBlock:
      maxRetries: 5
      initialDelayMs: 500
      maxDelayMs: 8000
      jitterRatio: 0.25

将对应段的 maxRetries 设为 0 可关闭该策略。配置值畸形会导致插件加载失败并指明 offending key,而不是静默关闭重试。

若希望非 429 的 provider 重试退避形状接近 OMP,可在 provider 策略中保持 RATE_LIMIT 于 retryableCodes(插件移除后仍可作为 429 兜底):

retryPolicy:
  mode: normal
  maxRetries: 10
  retryableCodes:
    - EMPTY_RESPONSE
    - RATE_LIMIT
    - SERVER
    - TIMEOUT
    - TRANSPORT
  backoff:
    initialDelayMs: 500
    maxDelayMs: 8000
    jitterRatio: 0.25

插件激活时由 bundle 优先处理 429;RATE_LIMIT 留在列表中主要用于未安装本插件时的回退。

典型用法

1、确认 DSH profile 名称,执行上述 dsh plugin ... add 命令。
2、重启 DSH,遇 429 或 thinking 绑定拒绝时观察会话中的 llm/retry 相关事件与 UI。
3、若限流仍过于激进或过于保守,在 cordis.patch.yml 调整 floorMs、maxDelayMs 或 maxRetries;多上游场景可适当提高 thinkingBlock.maxRetries。
4、需要与 OMP 其他非重试能力(模型/凭证回退链等)对齐时,README 明确说明本插件未实现那些链路,仅覆盖两种失败类型。

适用场景与注意

适合谁: 使用 DSH 且经 OMP 或多通道代理访问模型、经常遇到 429 或 thinking 块 400 的开发者;希望在不修改 DSH 核心的前提下获得更接近 OMP 的等待与绑定重试行为。

局限(摘自上游文档):

  • 不是通用重试框架,也不等同于 Ghostty;只处理 429 与 thinking 块绑定拒绝。
  • 重试不改写历史;若拒绝持续出现,可能是会话中模型或 tool schema 已切换导致身份变化,预算耗尽后回合仍会结束。持久修复在上游:例如发送 anthropic-beta: thinking-binding-controls-2026-08-01 并设置 thinking.block_binding.prefix_mismatch_behavior: "drop_block",或在客户端丢弃陈旧块。
  • 未实现 OMP 的 model/credential fallback chains。
  • 上游 Retry-After 超过 maxDelayMs 时不会继续等待。

插件以当前 DSH 进程权限运行;安装前请自行审阅 源码 与 MIT 许可。package.json 显示当前发布版本为 0.2.2;开发构建要求 Node >=22.19.0。

结尾

dsh-omp-retry 用最小侵入的方式补上 DSH 内置执行器在 429 与 thinking 绑定上的终态缺口,并与 dsh-llm-retry、内置 executor 分工明确。目录与仓库:

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

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

小夜