Replies: 4 comments 3 replies
Evidence Chain — Three Failure Entry Points, One Recovery GapThe invariant "every Entry 1:
|
Suggested Fix (Updated)——Update to the Suggested Fix (Option A) posted earlier:Option A: Append recovery
|
|
和 #1593 / #4309 同类: dsh-session-surgeon 不会发明缺失的 tool/result。 dsh plugin --profile web add "github:xiaoshenming/dsh-session-surgeon#main" |
|
不是说会话医生有问题——谢谢把检测需求写清楚。 inspect 警告:会加,已经写进 main。 预防 vs 修复:互补,不是二选一。
所以:引擎侧最小修复关掉写入缺口;surgeon 负责已经中毒的日志的诊断。引擎修上之后,需要我们诊断的会话会变少——这正是我们想要的。 安装仍是: dsh plugin --profile web add "github:xiaoshenming/dsh-session-surgeon#main"然后 |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Summary
When a tool call fails through any of three failure paths (
preparethrows /dispatchrejects /finalizethrows),tool/callis already appended but notool/resultis ever written. The session becomes permanently unusable — every subsequent request is rejected by the model API withINVALID_REQUEST(400).The engine already owns the recovery logic (
appendSkippedToolCallatdsh-agent-loop/lib/index.js:274-290) and applies it on the abort path. But the failure path bypasses it entirely — the outer catch (:252-255) only drains dispatches and rethrows, never writing recovery. The code's own JSDoc (:159-160) documents this asymmetry: "Scheduler failure drains dispatches without committing synthetic recovery results."Suggested fix: Apply
appendSkippedToolCallin the failure catch path — reuse existing machinery, no new code paths needed.Trigger Condition
preparethrows /dispatchrejects /finalizethrowstool/callis already durable,tool/resultis never writtenMinimal Repro
Related
Environment
@deepseek-ai/dsh-agent-loop@0.1.1-rc.2audit20260822Detailed evidence chain and fix analysis follow in the comments below.
摘要
当工具调用经由任意一条失败路径(
prepare抛错 /dispatch拒绝 /finalize抛错)失败时,tool/call已被写入,但tool/result永远没有写出。会话因此永久不可用——此后每一次请求都会被模型 API 以INVALID_REQUEST(400) 拒绝。引擎已经有恢复逻辑(
appendSkippedToolCall,位于dsh-agent-loop/lib/index.js:274-290),并且在 abort 路径上应用了它。但 failure 路径完全没有走这条逻辑——外层 catch (:252-255) 只 drain 掉 dispatches 然后重新抛出,从不写恢复结果。代码自己的 JSDoc (:159-160) 就记录了这种不对称:"Scheduler failure drains dispatches without committing synthetic recovery results."建议修复:在 failure 的 catch 路径中应用
appendSkippedToolCall——复用现有机制,无需新增代码路径。触发条件
prepare抛错 /dispatch拒绝 /finalize抛错tool/call已持久化,tool/result永远未写出最小复现
相关 issue
详细证据链与修复分析见下方跟帖。
署名 / About this report
EN: Reported by the OfferKuai (Offer快) Team — an AI startup building full-lifecycle job-application services, guided by the belief that *"users need results, not repeated conversations." We use DeepSeek Harness as part of our daily development workflow; this report is our way of contributing back to the ecosystem.
ZH: 本报告由 OfferKuai(Offer快)团队提交 —— 一家专注 AI 全流程求职托管的创业团队,核心理念是「用户要的是结果,不是重复对话」。我们将 DeepSeek Harness 用于日常开发工作流,这份报告是我们对社区的回馈。
All reactions