dsh-plugin-auto-continue
为 DeepSeek Harness(DSH)提供"对话失败时自动继续"能力的事件插件。
对话中途的网络抖动、限流(RATE_LIMIT)、服务端错误(SERVER)、超时(TIMEOUT)、空响应
(EMPTY_RESPONSE)等故障,通常会在内置重试耗尽后直接终结当前轮次;工具/扩展抛出的异常
也会直接关闭轮次。本插件在这两个层面上按有界、可取消、可观测的方式自动续接对话。
工作原理
插件挂载了两个协作层,并且永远让既有恢复机制优先(不与 dsh-llm-retry 或
provider 策略竞争):
第 1 层:模型请求级回退(agent/request-error waterfall)
- 监听器总是先调用
next():若下游(通常是 dsh-llm-retry 的 provider 策略)
已返回 { kind: 'retry' },则原样放行,完全不干预。
- 只有当失败即将成为终态时,本插件才接管:记录一条
auto-continue/retry 会话事件,
按指数退避(默认 1s 起、上限 30s、含抖动;若 provider 给出 Retry-After 则优先
采用)等待后返回 { kind: 'retry' },使同一轮次的同一步骤原地续跑。
- 每个 (agent, turn, step) 默认最多回退 3 次,超出后放行为终态,交给第 2 层。
- 仅对默认允许的失败码生效:
EMPTY_RESPONSE / RATE_LIMIT / SERVER / TIMEOUT / TRANSPORT。认证失效、配额耗尽(NO_ADAPTER / AUTH / QUOTA 等)不会无意义重试。
第 2 层:轮次级续接(turn/end 会话事实)
当顶层会话的一个轮次仍以 reason.kind === 'error' 结束(扩展异常、预算耗尽等):
- 通过
agent.followup() 排队一条可见的续接消息(来源为 kind: 'plugin',
plugin 标识为本包名),由新轮次接续未完成的工作;
- 仅对根 agent 生效(subagent 委派不受影响,可用
includeSubagents 放开);
- 每条错误连击(streak)默认最多续接 2 次,冷却期(默认 30s)内不重复触发,
轮次正常完成即清零;
- 触发前会再次校验 agent 存活、处于 idle、且未被替换。
所有动作都留痕:第 1 层写入 auto-continue/retry 事件,第 2 层发送可见消息,
同时输出 auto-continue: 前缀的日志。
安装
方式 A:共享 fallback 目录 + 用户补丁层(免 pnpm,本机已采用)
-
将整个 dsh-plugin-auto-continue/ 目录放到
$DSH_HOME/profiles/node_modules/ 下(Windows 默认即
C:\Users\<你>\.dsh\profiles\node_modules\)。该目录是 harness 维护的
平铺解析 fallback,Node 从任何 profile 向上查找依赖都会经过它,且
healProfilesModuleFallback 只管理自己的闭包链接、不会清理外来目录。
-
在目标 profile 的用户补丁层($DSH_HOME/profiles/<name>/cordis.patch.yml)
中加入:
- insert:
- id: auto-continue
name: dsh-plugin-auto-continue
config: {}
-
保存即可——用户补丁层被热加载(watchUserPatches),长驻进程无需重启;
若未生效,重启一次 DSH 即可。
方式 B:标准 bundle 安装
dsh plugin --profile web add D:/path/to/dsh-plugin-auto-continue
dsh plugin 会用 pnpm 完成安装,并把声明了 dsh.bundle.patch 的包自动追加进
dsh.profile.bundles,随后由包内的 cordis.patch.yml 挂载同一行。升级用
pnpm update 即可。
本包对 @deepseek-ai/dsh-llm 与 @deepseek-ai/cordis 的依赖声明为可选 peer,
运行时经由 harness 安装闭包(fallback 目录)解析,无需单独安装。
配置
在插入行上给出 config 即可覆盖默认值(未给出的键使用默认;未知键会启动报错):
- insert:
- id: auto-continue
name: dsh-plugin-auto-continue
config:
request:
enabled: true # 是否启用请求级回退重试
maxRetries: 3 # 每个 (agent, turn, step) 的最大回退次数
initialDelayMs: 1000 # 退避起点
maxDelayMs: 30000 # 退避上限(也钳制 Retry-After)
codes: [EMPTY_RESPONSE, RATE_LIMIT, SERVER, TIMEOUT, TRANSPORT] # 允许续接的失败码
turn:
enabled: true # 是否启用轮次级续接
maxRestarts: 2 # 每条错误连击的最大续接次数
delayMs: 2000 # 续接前的延迟
cooldownMs: 30000 # 两次续接之间的最短间隔
includeSubagents: false # 是否也对 subagent 生效
codes: null # 缺省 = request.codes + UNKNOWN
message: "[自动续接] 上一轮对话因错误中断({code})。请从中断处继续,完成未完成的任务。"
message 模板支持占位符:{code}(失败码)、{message}(截断后的失败信息)、
{attempt}(本次是第几次续接)。
观测与排障
- 日志:
auto-continue: 前缀(info/warn)。
- 会话日志:搜索事件类型
auto-continue/retry;第 2 层的续接消息在聊天流中可见。
- 完全关闭某一层:把对应
enabled 设为 false;卸载见下。
卸载
从 profile 的 cordis.patch.yml 删除对应 - insert: 行(热生效);若为方式 B
安装,再执行 dsh plugin --profile <name> remove dsh-plugin-auto-continue。
删除目录本身即可完成彻底清理。
License
MIT