dsh-plugin-auto-retry:接住官方重试放手的模型请求失败

前言

在 DeepSeek Harness(DSH)里跑智能体时,模型请求偶发失败很常见:限流、网关兜底错误码、官方重试预算用尽等。DSH 自带 @deepseek-ai/dsh-llm-retry,挂在 agent/request-error 瀑布流的外层,按 provider 的 retryPolicy 重跑失败请求。但它只认固定几个失败 code、预算有界(normal 模式默认 5 次),适配器未声明策略时还有一套默认边界——于是不少失败一次都不会重试,转录里往往只剩被截断或替换后的报错。

社区插件 dsh-plugin-auto-retry(维护者 aqiu817,分类:模型推理)挂在官方执行器主动放弃之后:官方决定不重试时会调用 next(),失败会流到本插件;插件按「接续官方退避曲线」再试若干次,并在轮次尾部用默认折叠面板展示原生转录里被丢掉或替换的完整报错。不注入伪造消息,不替换、不改动任何官方插件。

这是什么

dsh-plugin-auto-retry 是 DSH 宿主侧 bundle 插件(npm 包名 dsh-plugin-auto-retry,当前版本 0.1.0,MIT 许可证,要求 Node.js >= 22)。它解决两类问题:官方 @deepseek-ai/dsh-llm-retry 因 code 不在默认可重试集合、预算耗尽或尚无 retryPolicy 而跳过的失败;以及读者在 UI 里看不到完整失败细节的情况。

与官方重试的关系

处理顺序可以概括为:

模型请求失败
   │
   ├─ dsh-llm-retry(外层)
   │     ├─ 可重试且预算未耗尽 → backoff → retry(本插件不参与)
   │     └─ 否则 → next()
   │
   └─ auto-retry(本插件)
         ├─ 硬拒绝 / 不在白名单 / 超出额外预算 → 终态
         └─ 否则:持久 → 可取消等待 → retry

官方在决定重试时不会调用 next(),因此不会出现「官方与本插件各重试一次」的双重试。官方 normal 策略默认可重试 code 为 EMPTY_RESPONSE、RATE_LIMIT、SERVER、TIMEOUT、TRANSPORT,maxRetries 为 5,退避约 500ms 至 10000ms(抖动 0.1)。

本插件典型补位包括:code 不在官方 retryableCodes(如部分适配器的 PROVIDER_ERROR、PI_AI_ERROR、QUOTA、INVALID_REQUEST 等);官方预算用尽后的额外尝试;在最终适配器选定前、retryPolicy === undefined 时的失败(限白名单)。它不处理工具/middleware 失败、直接 ctx.llm.stream() 消费、用户 aborted,以及 CONTEXT_WINDOW_EXCEEDED / IMAGE_OFFLOAD_REQUIRED 等由压缩或图片卸载负责的终态。

核心功能

  1. 下游接续重试:监听 agent/request-error,在官方 next() 之后做资格判定;命中白名单且未超 extraRetries 时持久状态、按配置的初始延迟、上限与抖动等待后返回 { kind: 'retry' }。
  2. 可配置白名单与预算:在官方 5 次之外默认再允许 3 次(extraRetries);默认愿意接手的 code 含官方那 5 个,另加 PROVIDER_ERROR、PI_AI_ERROR。认证失败、无效模型、上下文溢出等落在硬拒绝集合,不可通过配置绕过。
  3. 完整报错面板:浏览器半部在轮次尾部提供默认折叠面板,展示转录中丢失的完整错误信息;配置表单通过 Plugins 页面的组合包级 plugins.bundle.config 提供(命名空间 auto-retry)。
  4. 不冲突保证:无客户端注入伪造消息;失败发生在打开的 step 内部、工具结果合成之前,不诱导模型重跑带副作用的工具;尊重同一 signal 的取消语义。

安装与启用

推荐通过 plugin_manager 安装 bundle,由它写入 profile 依赖与 patch:

plugin_manager(action: "install_bundle", target: "dsh-plugin-auto-retry")

手工安装时,在 profile 的 package.json(路径形如 ~/.dsh/profiles/<name>/package.json)增加依赖,并把包名加入 bundles:

{
  "dependencies": {
    "dsh-plugin-auto-retry": "^0.1.0"
  },
  "dsh": {
    "profile": {
      "bundles": [
        "@deepseek-ai/dsh-base",
        "@deepseek-ai/dsh-web-app",
        "dsh-plugin-auto-retry"
      ]
    }
  }
}

本地开发可把依赖改为目录链接,例如 "dsh-plugin-auto-retry": "link:/absolute/path/to/dsh-plugin-auto-retry"。cordis.patch.yml 会通过 dsh.bundle.patch 自动进入 patch 列表。装好后可在 Plugins 页面确认是否出现 auto-retry;本插件不是 required bundle,组合失败不会写启动日志。

卸载时删除依赖与 bundles 中对应行并重新安装依赖即可,无残留状态。

配置

在侧栏 插件 → 打开 dsh-plugin-auto-retry 组合包,在页面上的表单修改。六项均为 .volatile():改 enabled: false 可中途掐断正在跑的重试链,且不会重载整个 fiber。

字段 类型 默认 说明
enabled boolean true 总开关
extraRetries integer 3 官方预算之外的额外尝试次数;0 表示不介入
initialDelayMs integer 1000 官方未试过时的起步延迟(0–600000)
maxDelayMs integer 60000 延迟上限(0–600000)
jitterRatio number 0.2 对称抖动比例(0–1)
retryableCodes string[] 见 README 愿意接手的错误 code,至少保留 1 个

页面上 retryableCodes 以分组开关呈现:默认开启含 EMPTY_RESPONSE、RATE_LIMIT、SERVER、TIMEOUT、TRANSPORT、PROVIDER_ERROR、PI_AI_ERROR;QUOTA、INVALID_REQUEST、UNKNOWN 等需按需开启;AUTH、ABORTED、CONTEXT_WINDOW_EXCEEDED 等列为永不重试且开关禁用。若希望完全不介入,应使用 enabled: false 或 extraRetries: 0,而不是清空 code 列表(空列表在宿主侧会回落到默认白名单)。

典型用法

  1. 安装 bundle 后保持默认配置,即可在官方 5 次重试用尽或遇到 PROVIDER_ERROR、PI_AI_ERROR 等时自动再接 3 次,并查看折叠面板中的完整报错。
  2. 使用中继网关且常遇 QUOTA 或 INVALID_REQUEST:在 Plugins 配置里打开对应 code 开关后保存(需自行判断这类失败是否值得重试)。
  3. 仅需报错展示、不要额外重试:设 extraRetries: 0,或关闭 enabled。

装好后可执行 npm test(包内 contract.test.mjs 等)做契约与稳定性检查;发布前上游使用 prepublishOnly 跑测试。

适用场景与注意

适合长期用 DSH 对话/智能体、路由到 dsh-llm-pi-ai、dsh-plugin-kilo-gateway 等适配器且遇到过「一次失败就结束整轮」或转录报错不全的开发者。

务必注意:插件以当前 DSH 进程权限运行,安装前请阅读 GitHub 仓库 源码与 MIT 许可证,确认符合你的安全与合规要求。UNKNOWN 等非 HarnessError 场景需手动加入白名单才会重试。社区目录 SkillHub 插件页 与 DeepSeek / 幻方无官方从属关系,DSH 生态奉行「一切皆插件」,本包为社区维护的模型推理类扩展。

结尾

dsh-plugin-auto-retry 不替代官方 @deepseek-ai/dsh-llm-retry,只在官方 next() 之后接续退避与预算,并把完整失败细节还给读者。需要安装命令、配置边界与限制列表时,以仓库 README 为准。

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

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

Xiaoye