DeepSeek Harness 的「自动继续」插件:当一回话因为模型重试耗尽、供应商报错、 请求超时、或输出撞上长度上限而异常结束时,自动发送「继续」,让工作接着跑。 在聊天框「+」菜单里提供一行 「自动继续」+ 滑动开关(默认靠左「关」,点击滑至右侧「开」, 滑块上带「开 / 关」字样视觉反馈)。
长任务跑到一半,常常因为一些「非用户意愿」的因素断掉:
- 模型供应商临时 5xx / 限流,重试几次都没救回来;
- 请求超时、网络抖动;
- 单次输出太长,撞上
max-tokens天花板,话没说完就停了; - 其他把一回话以错误结束的情况。
这些在 DeepSeek Harness 里最终都收敛成同一条事实:一回话(turn)异常结束,
会话日志里写一条 turn/end + 结构化的结束原因。本插件只盯这一条事实:
回合异常结束 → 等一个小的冷却时间 → 用 DSH 自己的公开 API
(agent.followup(),和「目标续跑」走的是同一条路)投递一条「继续」,
让对话继续。
| 方案 | 评价 |
|---|---|
自己接管 agent/request-error 做重试 |
❌ 会和 llm-retry 抢同一个瀑布;重试策略该由 provider 配置决定 |
| 包一层 LLM 中间件重发请求 | ❌ 只能救「单次请求」,救不了「回合已经失败结束、但工作没做完」这个真正的场景 |
观察 turn/end + agent.followup('继续')(本插件) |
✅ 用 DSH 自己的稳定事件与公开 API;对所有导致回合异常结束的因素统一生效 |
关键点:它不关心是哪种中断。模型重试、超时、供应商报错、输出截断——
这些在 DSH 里最终都变成一条 turn/end + 结构化原因。插件只对这一条事实做判断,
因此天然覆盖「等其他因素」。
- 聊天框「+」菜单里多出一行:
自动继续+ 右侧滑动开关,默认靠左「关」, 点击滑至右侧「开」,滑块上显示「开 / 关」字样。 - 开关走 DSH 自己的 settings 通道,持久化、刷新/重启后保持。
- 回合失败 / 输出截断后,自动发送「继续」,在对话流里显示为一条可展开的上下文行
(不冒充用户消息,来源标注为
plugin: auto-continue)。 - 安全围栏(详见 设计文档 §5):
- 用户按「停止」永不自动续跑;
- 人类插话即让路;
- 只在真空闲时发,不打断正在跑的回合;
- 连续续跑次数封顶(
maxStreak,默认 12),防死循环烧钱; - 默认只管根 agent,不干扰子 agent 编排;
- 不做「卡住看门狗」(长命令本就会长时间静默,那种看门狗必然误伤)。
通过 Settings → Plugins → auto-continue,或直接编辑 cordis.patch.yml 的 config:
| 字段 | 默认 | 说明 |
|---|---|---|
enabled |
false |
总开关(「+」菜单的滑动开关写的就是它;默认关) |
prompt |
继续 |
自动发送的正文 |
delayMs |
1500 |
回合结束后等多久再发(留出结算时间) |
maxStreak |
12 |
连续自动续跑上限,只被真实人类消息清零 |
onError |
true |
回合失败后续跑 |
onMaxTokens |
true |
输出截断后续跑 |
onAborted |
false |
非用户原因中止后续跑(用户停止不受此项影响,永不续跑) |
onBlocked |
false |
被阻断后续跑 |
includeSubagents |
false |
是否也管子 agent |
announce |
true |
预留:是否把续跑记录进会话日志 |
详见 部署文档。最简步骤:
# 1. 把本目录放进你的 DSH 插件目录(例:/root/普通目录/dsh-auto-continue)
# 2. 在 web profile 里登记
dsh plugin --profile web add /root/普通目录/dsh-auto-continue
# 3. 把插件加入 bundle 列表(见部署文档),然后重启 dsh
systemctl restart dsh.service # 或你的等价方式重启后刷新页面,点聊天框的「+」,即可看到「开启自动继续 / 关闭自动继续」。
本仓库带三层测试,从单元到真实主机端到端:
node test/engine.test.mjs # 决策引擎:13 个用例
node test/e2e.test.mjs http://127.0.0.1:3098 /path/to/work # 真实失败回合 → 自动继续 → 封顶
# 浏览器「+」菜单:
node test/menu.probe.mjs http://127.0.0.1:3098 # 需要 playwrighte2e.test.mjs 会起一个没有可用凭证的隔离 DSH 主机,让每次模型请求都真实失败,
然后断言:失败回合 → 插件真的发了「继续」→ 连续 maxStreak 次后真的停手。
MIT