LLM 自动重试设置卡片:在设置页实时调整重试次数、退避与抖动,并可勾选额外可重试错误码(retryableCodes)—— 默认补入 INVALID_REQUEST,OpenAI thinking 模式 HTTP 400 reasoning_text 报错开箱即自动重试。
安装
# npm 包(预构建)
dsh plugin --profile web add dsh-llm-retry-settings
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:zeng6125-rgb/dsh-llm-retry-settings
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
DSH「LLM 自动重试」设置卡片:在 设置 → General 里调整自动重试的次数与退避时间,宿主 @deepseek-ai/dsh-llm-retry 实时生效。0.1.7 起还能在回答被输出 token 上限截断时自动续写;0.1.9 起额外错误码与续写提示词都能自己写。
功能
- 自带设置 UI(客户端 bundle
lib/client.js):一张位于 设置 → General 的卡片,无需另外装 UI 包。 - 覆盖
agent/request-error重试策略中的maxRetries、initialDelayMs、maxDelayMs、jitterRatio。 - 0.1.12 修复 会话格式 v4 下自动续写投递失败:消息 source 必须是 producer-owned 形态,续写消息改携
source.kind = "plugin:dsh-llm-retry"(退役的{kind:"plugin"}包装不再被接受);host.log 的「续写消息已入会话」识别同步恢复。 - 0.1.11 新增 支持新内核 0.1.7-alpha.1(设置 API 迁移到
SettingsForms:volatile 表单字段、loader/volatile-update实时同步、卡片经remote.settings读写)。 - 0.1.11 新增 改善设置卡片滑动流畅度,修复 bug。
- 0.1.10 新增 卡片底部重试观测面板(只读):请求失败重试、自动续写、触顶、让位用户的计数,按错误码与 provider/model 拆分,并列出当前会话模型(覆盖规则照抄即可),可展开日志尾部。
- 0.1.10 新增 按 provider / model 的策略:按顺序取第一条命中的规则,支持
*通配,数值留空即继承全局值。 - 0.1.10 新增 退避曲线 + 等待预算、「重试彻底失败后也续写」开关(仅瞬时错误)、提示词模板,以及跟随内核语言的中英文界面。
- 0.1.9 新增 可以直接在卡片上输入自定义错误码(
自定义分组):provider 抛出的码不在已知清单里时,输入(如MY_PROVIDER_BUSY)后点添加即可。输入会自动转大写并校验(仅限A-Z 0-9 _ - .),重复或非法输入给出内联提示,码原样进入retryableCodes。 - 0.1.9 新增 续写提示词可自定义(
continuationPrompt):留空使用内置文案,也可以自己写一句,适配不同中转/模型对措辞的偏好。 - 0.1.8 修复 自动续写现在真的会发出去了。宿主半边两道时机坑:
session/event是在Session.append内部同步派发的,在监听器里直接排续写会撞session append cannot reenter while another append is being published;绕开之后又发现此刻唤醒 agent 会被驱动静默丢弃(wakeDriver只在 maintenance/abort 下才 latch),消息就永远卡在队列里。现在改成先await agent.whenIdle()再投递,投递前复核(已开新回合 / 你重新发言 / 会话已 dispose 则放弃)。 - 0.1.8 新增 宿主半边把每一步决策写进
~/.dsh/logs/dsh-llm-retry-settings/host.log(低频、256 KB 封顶),设置卡片上也标了这个路径。见 排错。 - 0.1.7 新增 重新按当前宿主核对错误码清单:补入
PI_AI_NOT_WARMED(适配器预热竞态,退避后重试通常能成)与三个琥珀色「重试无意义」码(UNKNOWN_MODEL、UNSUPPORTED_OPTION、REQUEST_EXTENSION)。同时澄清TIMEOUT:SSE 卡流(stream idle 看门狗)就是以TIMEOUT上报,并没有独立错误码,宿主默认重试码表已覆盖。 - 0.1.7 新增 输出截断自动续写(
autoContinue,默认关闭)。撞到输出 token 上限不是请求失败——请求是成功返回的,只是finish = max-tokens——所以任何重试策略都管不到它。开启后本插件监听turn/end,每次截断补一轮续写,最多连续maxContinuations次(模型正常说完或你重新发言即重新计数)。 - 0.1.7 新增 错误码 chip 按「重试有没有恢复价值」分六组:瞬时故障 → 限流与配额 → 请求与参数 → 内容与能力 → 凭证与鉴权 → 取消与兜底,组标题上标出该组已选数量;已选中的码仍在自己那一组内靠前。
- 0.1.5 新增 已选中的错误码自动靠前,未选中的排在其后;组内顺序固定,勾选时 chip 不会乱跳。(0.1.7 起改为在各分组内部靠前。)
- 0.1.3 新增
retryableCodes:可勾选的额外重试错误码,与各 provider 自带列表 合并(去重)而非替换。默认补入INVALID_REQUEST+PI_AI_ERROR,开箱即重试 OpenAI 式 HTTP 400(thinking 模式reasoning_text)与流式失败兜底码。 - 默认
enabled: false= 完全旁路:不开启覆盖时,不改动任何东西。
安装
前置:一个 DSH Desktop profile(web profile 位于 ~/.dsh/profiles/web)。
方式 A —— GitHub Release 安装包(推荐)
# 1. 从 v0.1.12 release 下载打包好的插件 tgz
gh release download v0.1.12 -R zeng6125-rgb/dsh-llm-retry-settings
# 2. 解压进 profile 的 node_modules
mkdir -p ~/.dsh/profiles/web/node_modules
tar -xzf dsh-llm-retry-settings-0.1.12.tgz -C ~/.dsh/profiles/web/node_modules/
mv ~/.dsh/profiles/web/node_modules/package \
~/.dsh/profiles/web/node_modules/dsh-llm-retry-settings
# 3. 在 profile 里注册 bundle,然后重启 DSH
# 在 ~/.dsh/profiles/web/package.json 的 dsh.profile.bundles 里加 "dsh-llm-retry-settings"
方式 B —— dsh CLI / pnpm(需要 git + 网络)
dsh plugin 命令会把参数转发给 profile 目录里的 pnpm:
# 从 git 仓库安装(pnpm 会 clone;lib/ 已提交,无需构建)
dsh plugin --profile web add github:zeng6125-rgb/dsh-llm-retry-settings
# 或从 release tarball 地址安装
dsh plugin --profile web add https://github.com/zeng6125-rgb/dsh-llm-retry-settings/releases/download/v0.1.12/dsh-llm-retry-settings-0.1.12.tgz
装完还需要在 profile 里启用:把 "dsh-llm-retry-settings" 加进 dsh.profile.bundles(或使用 Desktop 的插件管理 UI),然后重启 DSH。
注意:命令是
dsh plugin(dshCLI 的子命令),不是dsh-plugin。dshCLI 随 Desktop 应用内置;如果不在PATH里,用 app 的 bin 调用,例如node "<app>/node_modules/@deepseek-ai/dsh/lib/bin.js" plugin --profile web ...。
方式 C —— 源码
git clone https://github.com/zeng6125-rgb/dsh-llm-retry-settings.git
cd dsh-llm-retry-settings
npm install
npm run build # node scripts/build.mjs → lib/index.js + lib/client.js(不需要 DSH 源码树)
把本地构建 link 进 profile 并注册 bundle:
dsh plugin --profile web link "$PWD"
# 然后把 "dsh-llm-retry-settings" 加进 dsh.profile.bundles 并重启 DSH
使用
- 打开 DSH 设置 → General。
- 找到 LLM 自动重试 卡片。
- 打开 开启覆盖(
enabled)。 - 设置
maxRetries/initialDelayMs/maxDelayMs/jitterRatio,按需点选 可重试错误码 chip;清单里没有的码可以在自定义分组里输入后点添加,最后点 保存。 - 需要的话打开输出截断自动续写(
autoContinue)并设置maxContinuations上限——它与上面的重试覆盖互不影响。续写要发的那句话可以在续写提示词里改,留空即用内置文案。
改动会写入 dsh-llm-retry 设置命名空间,重试引擎实时生效。
排错
回答被截断但没有自动续写。 宿主半边会把每一步决策写进
~/.dsh/logs/dsh-llm-retry-settings/host.log——一个事件一行,超过 256 KB 重写一次。
桌面版的 ctx.logger 不落任何可读文件,所以这个日志是唯一的观察口。看最后几行:
- 启动处没有
activate v…→ 插件没被加载(查 profile 里的dsh.profile.bundles)。 activate v…会写明当前跑的是哪一版构建——不是你刚装的那版,就是没重启 agent。settings registered … autoContinue=false→ 开关没开。- 有
turn/end …但后面没内容 → 那一刻autoContinue是关的,或maxContinuations是0。 bail …→ 原因在行里(该会话没有 agent 实例、followup不可用……)。放弃投递 …→ 等 agent 空闲期间情况变了(开了新回合、你重新发言、会话被 dispose),这条过期续写按设计丢弃。续写已投递 … chain=N/M→ 已排队发出。连续续写触顶表示到了maxContinuations上限;模型正常说完或你发一条消息即重新计数。
改宿主半边(lib/index.js)必须重启 DSH。 客户端卡片刷新页面即可,agent 不会热重载。
配置项
| 键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enabled |
boolean | false |
是否开启重试策略覆盖。 |
maxRetries |
integer(≥ 0) | 2 |
最大重试次数(0 = 不重试)。 |
initialDelayMs |
integer(≥ 1) | 500 |
首次重试前的初始退避(毫秒)。 |
maxDelayMs |
integer(≥ 1) | 10000 |
退避时间上限(毫秒)。 |
jitterRatio |
number(0–1) | 0.1 |
退避抖动比例(0 = 无抖动)。 |
retryableCodes |
string[] | ["INVALID_REQUEST", "PI_AI_ERROR"] |
额外视为可重试的错误码,与各 provider 自带列表合并。 |
autoContinue |
boolean | false |
回合因输出 token 上限被截断时,自动补一轮「继续」。 |
maxContinuations |
integer(≥ 0) | 2 |
同一次截断后连续续写的上限(0 = 永不续写)。 |
continuationPrompt |
string | "" |
截断后自动发给模型的那句话;留空(或只有空白)使用内置文案。 |
continueOnError |
boolean | false |
重试次数用尽后,若结束原因是瞬时错误(超时 / 传输 / 服务端 / 流中断 / 空响应),也补一轮续写;确定性错误不补。 |
overrides |
array | [] |
按 provider / model 的策略。每行 { provider, model, maxRetries, initialDelayMs, maxDelayMs, jitterRatio };* 或留空 = 任意,数值 -1 = 继承全局值。按顺序取第一条命中。 |
logPath |
string | (宿主注入) | 只读。 宿主日志绝对路径,由宿主半边注入给卡片的「打开日志」按钮,不写回设置文件。 |
工作原理
宿主半边注册 dsh-llm-retry 设置命名空间(schema 校验 + 持久化 + live 同步),并在 agent/request-error 监听链最前端 prepend 改写 retryPolicy,官方 @deepseek-ai/dsh-llm-retry 的 recover 直接消费覆盖后的策略:
agent/request-error → [本插件:覆盖次数/退避] → dsh-llm-retry recover
自动续写那一半走的是会话事件流,因为被截断的回复本质上是一次成功的请求:
适配器 finish="max-tokens" → agent-loop turn/end{reason:"max-tokens"} → [本插件] → agent.followup(continuationPrompt || 内置文案)
不能用 agent/turn-stopping:它的 payload 里没有结束原因,分不清「模型说完了」和「模型被截断了」。
续写消息的 source.kind 是 plugin,因此聊天里渲染成一条标注 dsh-llm-retry 的注入上下文行,而不是伪装成你亲自发的消息。
构造期种子事件(resume / fork / replay)不会进入 session/event,所以重新打开一个历史上被截断过的旧会话不会触发续写。
哪种措辞有效取决于 provider:有些中转不会在下一轮请求里回显上一段的 reasoning,模型看不到自己的思考停在哪,就可能把任务从头重做。
遇到这种情况请改 continuationPrompt(例如让它直接作答、不要再长篇思考)——多发几条「继续」是解决不了的。
界面
设置 → General → LLM 自动重试 卡片。编辑采用草稿模式:点「保存」提交、「放弃」回滚;保存后会对快照做校验,显示 已保存 ✓ / 保存失败 ✗。
卡片内是两块互不影响的能力:上面的重试覆盖(次数 / 退避 / 抖动 + 分组错误码 chip,另有可自由输入码的 自定义 分组)与下面的输出截断自动续写(独立开关 + maxContinuations 上限 + continuationPrompt 输入框)。
关闭的那一块会置灰且输入框不可编辑,但开关本身仍可点击——开自动续写不需要先开重试覆盖。
依赖
- 宿主插件:
@deepseek-ai/dsh-llm-retry - 客户端运行时:
@deepseek-ai/dsh-client-web-react - DSH
settings服务
构建
npm run build # node scripts/build.mjs
npm run typecheck # tsc --noEmit
License
链接
同类插件
V1ki/dsh-plugin-subscriptions★ 417
把 ChatGPT(Codex)、Claude、Grok 订阅当作 DeepSeek Harness 的 LLM 提供方:设置页登录、模型目录、用量展示,以及 image_generate、video_generate 与 x_search 工具。
Mars-Sea/dsh-commandcode-provider★ 359
非官方 Command Code 模型接入插件:注册 `commandcode` 路由,带实时模型目录与推理强度支持。
corrinehu/dsh-workbuddy-connect★ 272
将 WorkBuddy 桌面 App 包含的模型自动接入 DeepSeek Harness,在 DSH 对话窗口里零配置使用。
cv-superding/dsh-deepseek-web-login★ 208
新增 deepseek-web provider,把 chat.deepseek.com 网页端模型接入 DSH:浏览器登录抓取、PoW 请求签名、SSE 流式传输与基于提示词的工具调用。
volcengine/ark-cli#ark-plan-api★ 139
在 DSH 原生模型选择器中注册方舟 Agent Plan、Coding Plan 与后付费模型路由。
franksong2702/dsh-codex-connect★ 133
通过 ChatGPT OAuth 将 OpenAI Codex 模型接入 DeepSeek Harness,并提供可选的搜索与图片工具。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。