|
Important While reading the DSH 0.1.1-rc.1 code, I noticed a potential control-flow issue in the agent loop. A sticky The same logic appears to still be present in DSH 0.1.1-rc.2. The relevant code is in The code intentionally keeps However, lines 295–299 also use The potential failure sequence is:
|
Replies: 2 comments 2 replies
|
Answering the question directly: no, nothing else guarantees continuation, and the sequence you describe reproduces. I built the case you reasoned out — a step that ends WhyOne variable is answering two different questions.
Because both ride if (turnEnds && decision.messages.length === 0) breakAfter a tool call Fix shapeSplit the two roles. Keep let stopping: StepEndReason | null = null
...
const stepEnd = await this.step(decision.assembly)
stopping = stepEnd
if (stepEnd !== null && (turnEnds === null || turnEnds.kind !== 'max-tokens')) {
turnEnds = stepEnd
}then drive both break conditions off Reachability, and who is most exposedIt needs a steer to carry the turn past the truncated step, which the suite's own sticky-max-tokens test already demonstrates is an ordinary thing to happen. Worth flagging for anyone running a fork with context-overflow recovery: if you clamp Verified against the full suite after the change: 844 files, 14161 tests, zero failures. |
|
I built a bounded reference implementation against official Thank you @ShikangL for the exact failure sequence, and @nokkies for independently reproducing it and publishing the split-variable fix sketch. This implementation turns that analysis into a reviewable patch and cross-SDK receipt. The root issue is the conflation of two values: the durable turn outcome ( Evidence:
Reference branch: https://github.com/Jstn-1g/deepseek-harness/tree/reference/discussion-4622-max-tokens-tool-continuation Exact commit: Jstn-1g@91fa9ba This is a verified reference implementation, not a claim of upstream adoption. |
Answering the question directly: no, nothing else guarantees continuation, and the sequence you describe reproduces.
I built the case you reasoned out — a step that ends
max-tokens, a steer carrying the turn forward, then an ordinary tool call — and got two model calls where there should be three. The tool result is committed to the session log and no step ever reads it. Your reading of lines 285–299 is exactly right.Why
One variable is answering two different questions.
step()returnsnullto mean "another step is required so the model can read the tool result". That null is the only continuation signal the loop has. It also returns a reason, which is what the turn should report, andma…