dsh-messages-sanitizer · 自动修复孤立的 tool_calls,让 400 INVALID_REQUEST 不再卡死会话 #5514
Leeminjing
started this conversation in
Show Your Plugins!
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
dsh-messages-sanitizer · 自动修复孤立的
tool_calls,让400 INVALID_REQUEST不再卡死会话 Automatically repair orphanedtool_callsso400 INVALID_REQUESTerrors no longer break the session.一句话
工具调度崩溃后,会话历史里会留下「没有配对结果的
tool_calls」(或孤立的tool消息),下一轮请求就被 DeepSeek 接口反复用400 INVALID_REQUEST拒绝、会话卡死。本插件在运行时自动把messages数组修回合法,让对话继续——不改 harness 源码。解决什么问题
OpenAI 兼容协议要求
tool_calls与tool结果成对且紧邻出现。一次崩溃(例如工具调度在「记录 assistanttool_calls之后、产出tool结果之前」中断)就会留下孤儿调用:接口返回
400,重试时历史原封不动,于是被反复拒绝。这个故障类在官方仓库也有跟踪:#4843(残缺或孤立的tool_calls记录导致接口返回 400)。怎么工作(四层防御)
agent/status,主路径)—— 崩溃后把错误原样上报给 LLM 并唤醒它,下一步换工具 / 重试 / 向用户报告由 LLM 自己决定,保证 AI 消息始终是最后一条、对话不挂起。agent/pre-step)—— 下一轮请求构建前,把合成 errortool-result插到该步消息最前面,从源头杜绝 400。agent/request-error)—— 若仍因配对/紧邻违规返回 400,用 surface 替换修复历史后强制重试一次(幂等,不会无限重试)。llm/stream)—— 对每个请求做纯数组矫正(配对 + 紧邻重排 + 孤儿/重复/空消息丢弃)。安装(已收录于 awesome-dsh-plugin 精选榜,已上架插件市场)
与 #4843 的关系:互补,而非替代
#4843在 harness 源码层根治(agent-loop 剥离、llm-deepseek 合成 fallback id、compaction 按 callId 而非计数配对)。本插件是一个不改 DSH 源码、在运行时自动矫正messages数组的安全网:已中毒的旧会话、或跑在仍带该 bug(或工具调度崩溃)的 harness 版本上的用户,都能被自动救回并继续,不必等发版。链接与状态
dsh-messages-sanitizer→ https://www.npmjs.com/package/dsh-messages-sanitizer欢迎反馈;尤其如果你有真实崩溃日志,欢迎用它来验证。
dsh-messages-sanitizer · auto-repairs orphaned
tool_callsso400 INVALID_REQUESTnever stalls your sessionIn one line
After a tool-dispatch crash, session history is left with
tool_callsthat have no paired result (or orphanedtoolmessages); the next request is then rejected by the DeepSeek API with400 INVALID_REQUEST, and the session stalls. This plugin auto-repairs themessagesarray at runtime so the conversation continues — without touching the harness source.The problem
The OpenAI-compatible protocol requires
tool_callsto be paired and adjacent to theirtoolresults. A crash (e.g. tool dispatch interrupted after recording the assistanttool_callsbut before producing thetoolresult) leaves an orphaned call:The API returns
400, and because the history is unchanged on retry, it is rejected again and again. This class of failure is tracked upstream: #4843 ("Incomplete or isolatedtool_callsrecords cause the DeepSeek API to return 400").How it works (four layers of defense)
agent/status, primary path) — reports the error verbatim back to the LLM and wakes it; the LLM itself decides whether to switch tools, retry, or tell the user, so the AI message is always last and the conversation never hangs.agent/pre-step) — prepends a synthetic errortool-resultto the next request, eliminating the 400 at the source.agent/request-error) — if the API still returns 400 on a pairing/adjacency violation, repairs the history via surface replacement and forces one retry (idempotent — no infinite loop).llm/stream) — pure array correction on every request (pairing + adjacency reorder + orphan/duplicate/empty drops).Install(Listed in the awesome-dsh-plugin curated list)
Relation to #4843: complementary, not a replacement
#4843fixes the root cause in the harness source (agent-loop stripping, llm-deepseek fallbackid, compaction pairing bycallIdrather than count). This plugin is a runtime safety net that never modifies the DSH source — already-poisoned sessions, or sessions on harness builds that still carry the bug (or a tool-dispatch crash), are repaired and continue without waiting for the next release.Links & status
dsh-messages-sanitizer→ https://www.npmjs.com/package/dsh-messages-sanitizerFeedback welcome; if you have a real crash log, please try it against this plugin.
All reactions