mengge237/dsh-auto-continue0

@mengge237/dsh-auto-continue

DSH 插件 v0.3.1:max-tokens 自动续写 + 429/限流自动恢复(agent/status 挂点、完整 user message、429 熔断)。嘻嘻,我一定要用 DeepSeek harness

包名
@mengge237/dsh-auto-continue
版本
0.4.0
最近更新
2026年9月7日

安装

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:mengge237/dsh-auto-continue

dsh-auto-continue

lang status

嘻嘻,我一定要用 DeepSeek harness

DSH 回合被 max-tokens 输出上限截断(UI 提示"已达到输出 token 上限…发送'继续'")时, 本插件自动补一条"请继续";阿里 Token Plan 429/token-limit 触发时,冷却后自动重试; 上下文压缩把一整轮吞掉(检查点刚落、零产出就 completed)时,补一条"照检查点继续动手"。 目标只有一个:输出不断档,不用你手动救场

安装 / 卸载

dsh plugin --profile web add link:E:/S_Software/deepseek-harness/plugins/dsh-auto-continue
# 装完必须完全重启 dsh web(Settings → Plugins 可见 dsh-auto-continue)
dsh plugin --profile web remove dsh-auto-continue

备份:C:\Users\Lenovo\.dsh\profiles\web\cordis.yml.bak-*(dsh plugin 自动生成)。

30 秒自检(不用盯 GUI)

# 1) 插件是否真的挂上了(每次启动一行)
tail -3 ~/.dsh/auto-continue.log

# 2) 是否真的续写过:会话存档里找插件署名的 user/message
python ~/dsh-fixes/scan_auto_continue.py --since "2026-09-05 22:43:00"

auto-continue.log 会记录 已挂载(v0.4.0)…max-tokens 截断(turn N)→ 自动续写检测到 429/token-limit … → Xs 后自动重试(第 k/3 次)压缩检查点后零产出收尾(turn N,检查点之后 Xms 就 end 了)→ 补发续写; 不想留文件日志就 DSH_AUTO_CONTINUE_LOG=off(回归测试默认写 off,不污染运维日志)。

机制(对 dsh 0.1.2-rc.1 编译产物实证)

假设依据
根作用域 ctx.on('agent/status') 收得到所有 agentagentEvents()agent 融进 payload;官方插件(compaction-basic / goal-round-driver / sdk-jsonrpc-server)同款用法
收到 idle 时尾部 turn/end 已落盘turn()finallysession.append("turn/end")kick()finallysetPhase(idle)
reason.kind === 'max-tokens' / reason.error.{message,code}dsh-session TurnEndReasonMapLlmFailure
agent.followup(msg) 必须传完整 messagefollowup → send → inbox.splice(...,[message]),字符串会被当成残缺消息
inbox.hasPending 是 boolean getterdsh-agent Inbox(不是函数,别写 typeof === 'function'
插件目录解析不到 @deepseek-ai/dsh-llm实测 ERR_MODULE_NOT_FOUND(profile 的 node_modules 无 @deepseek-ai 作用域)→ v0.3.1 自带完整消息构造
service 取值必须留在事件派发那一帧内一旦 await 过再调 agent.followup(),cordis proxy 在 fiber.store 取不到 inject 服务,抛 cannot get required service "agents" in inactive context(ac-rig 实测)→ 所以消息构造同步、零依赖,max-tokens 分支同帧投递,只有 429 冷却才用定时器
真实 429 的 error.codeQUOTA 不是 RATE_LIMIT本机 turn/end 语料:429: {"message":"Allocated quota exceeded … #token-limit","code":"insufficient_quota"};而 Free quota exhausted / 余额不足 也是 QUOTA不可恢复 → 判定同时看 code 与文案,并用 DEAD_QUOTA 白名单排除
压缩检查点是一条 user/messagesource = {kind:'plugin', plugin:'compact'}dsh-compactionCOMPACT_CHECKPOINT_MARKER / isCompactCheckpointSource();UI 也靠它认折叠块
压缩能在轮内把整轮吞掉(v0.4 的靶子)本机 69 份存档 29 次压缩实测:13 次照常干活、7 次"回一句即 max-tokens"(旧分支已覆盖)、3 次 turn/start → user[plugin:compact] → turn/end[completed] 间隔仅 10~21ms 且零回复零工具。compaction-basic 自己就在 log 里写 shadowed N surface nodes:open-turn 压缩事务会 shadow 掉排在前的 surface 节点,本来该在这一轮跑的续写就此蒸发。这种 turn/end 的 kind 是 completed,跟正常收尾一模一样,只能靠形状认

行为与守卫

  • 触发:回合 max-tokens 截断、429 / Allocated quota exceeded / token-limit / insufficient_quota、 或压缩检查点之后零产出就 completed(三者共用同一套额度与守卫);
  • 每 agent 每 60 秒最多 DSH_AUTO_CONTINUE_MAX(默认 4)次自动续写,额度在排期时就预占(v0.3 是发送后才计数,突发会冲破上限);
  • 429 熔断:连续自动重试最多 DSH_TP_429_MAX_RETRIES(默认 3)次,之后停手等你手动继续—— 额度真尽时不会每分钟 4 次地无限重试;期间任何一次正常推进(completed)自动清零;
  • 新鲜度窗口 DSH_AUTO_CONTINUE_STALE_MS(默认 10 分钟):重启/恢复老会话时, 不会隔几小时突然补一句"请重新执行我上一条请求";
  • 尊重你正在打的字:inbox.hasPending 为真、或 agent 已被别的输入唤醒(非 idle)就放弃这一发并让出额度;
  • 全局错峰:自动消息之间至少间隔 DSH_TP_PACING_MS(默认 2.5s)+ 0~1.5s 抖动,平滑多会话的瞬时 TPM;
  • 429 恢复文案里的"已等待 X 秒"取真实计算值(v0.3 的 Math.max(C-p, C) 恒等于 C,pacing 白写);
  • 任何异常只记日志,绝不打断 agent 主流程。

环境变量

变量默认说明
DSH_AUTO_CONTINUE10 整体关闭
DSH_AUTO_CONTINUE_MAX4每 agent 每 60s 最大续写次数
DSH_AUTO_CONTINUE_STALE_MS600000只处理 N 毫秒内的 turn/end
DSH_TP_429_COOLDOWN_MS60000429 冷却(从 turn/end 时刻起算)
DSH_TP_429_MAX_RETRIES3连续 429 自动重试上限(熔断)
DSH_TP_PACING_MS2500自动消息全局最小间隔(另加抖动)
DSH_TP_REMINDER1429 恢复消息带"仅本会话提示"文案
DSH_AUTO_CONTINUE_CP_WINDOW_MS60000检查点 → turn/end 的最大间隔,超过就不算"压缩吞轮"(调小更保守,实测真样本是 10~21ms)
DSH_AUTO_CONTINUE_LOG~/.dsh/auto-continue.log行日志路径;off/0/空 关闭

回归测试(0 token,不连模型)

node --test test/          # 16 例:max-tokens 续写 / 429 冷却重试 / 熔断 / 上限 / 去重 / 消息完整性
                           # + 6 例压缩吞轮(补枪、有产出不插手、超窗不插手、同轮只一次、
                           #   max-tokens 优先走旧分支、无检查点的 completed 保持安静)

测试默认 DSH_AUTO_CONTINUE_LOG=off,不会往 ~/.dsh/auto-continue.log 里灌假 agent 的决策行。

与官方 goal 的分工

goal(create_goal / /goal)才是"多轮自主推进"的正道:它有 dsh-goal-round-driver 在每次 idle 时排下一轮,且能活过上下文压缩——SessionStartSource 类型里虽然写了 'compact',但 0.1.2-rc.1 的编译产物里没有任何调用方传它(只有 "startup""resume"), 而 dsh-goal 恰恰只在 agent/session-start 上无条件 activation = "disarmed"。 也就是说:同进程压缩不会解除 goal 的续期权,跨进程恢复才会(那种情况要人再 resume 一次)。

本插件管的是另一半:goal 只在你显式建了目标的会话里工作,而日常"我就想让它把这一件事做完" 的会话没有 goal,被 max-tokens / 429 / 压缩事务打断后就只能靠这里补一枪。 本机现状也印证两者互不重叠:5 份用过 goal 的存档一次都没触发压缩,29 次压缩全在没 goal 的长会话里。

版本

  • v0.4.0:新增"压缩吞轮"补枪(形状判定,见机制表最后一行);测试默认关文件日志,不再污染运维日志。
  • v0.3.1:修 3 个实测缺陷(残缺消息缺 role/idhasPending 守卫恒假、突发冲破每分钟上限), 新增 429 熔断、新鲜度窗口、idle 二次确认、行日志与回归测试。
  • v0.3:改为根作用域 agent/status + 读尾部 turn/end(v0.2 的 agent 作用域 session/event 收不到事件,故完全失效)。
  • v0.2:加 429 冷却重试与并发错峰。

说明

  • 自动续写继续消耗套餐 token(tokenplan/qwen3.8-flash),属"把订阅用出价值"的预期行为;
  • 只统计/只影响套餐 provider 之外的会话不做特殊处理:任何 provider 的 max-tokens 都会续,429 只对 token-limit 类文案生效;
  • 若官方将来内置 auto-resume,本插件即可废弃。