Repository navigation
fix: auto-retry invisible degenerate terminal turns (#732) - #734
Merged
Merged
Conversation
Contributor
📦 Built Package ArtifactBranch: Option A — Install from npm PR tag (recommended)npm install -g billion-context@pr-734Each push to this PR publishes a new version under the Option B — Download artifact
tar xzf billion-context-pr734.tgz
npm install -g packageThis comment is automatically updated on each push. |
This was referenced Sep 12, 2026
A reasoning model can end a turn with ONLY a thinking block — zero visible text, zero tool calls, status completed — most often right after a post-compress re-request, where it sees the freshly-shrunk context and "wraps up" into a silent thought. The client then receives an empty completed turn and stalls until manually nudged (#732). #673/#674 shipped the [degenerate-turn] detector as "the groundwork for auto-retry" but never implemented the retry. This adds it: when nothing has reached the client yet (forwardedAny=false — true for these rounds on wires whose round>1 framing is suppressed, e.g. Responses) and the turn is a genuine silent thought (sawThinking, not a legitimately empty/no-reasoning terminal), re-fetch once with an ephemeral continuation nudge. One-shot per request; the nudge is never committed to session state.
ranxianglei
force-pushed
the
2026-09-12_auto-mode-degenerate-turn
branch
from
September 14, 2026 15:00
8627545 to
22c609c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Fixes #732 — "AUTO model sometime stop".
A reasoning model can end a turn with only a thinking block (zero visible text, zero tool calls, status
completed) — most often right after a post-compress re-request, where it sees the freshly-shrunk context and "wraps up" into a silent thought. The client then receives an empty completed turn and stalls until manually nudged.Root cause (verified)
The user's log line at
14:43:32.513Zis the stop:compress; bili executed it server-side and re-requested (round 2).completedturn → empty turn forwarded → agent stalled until the next request (14:46:30).14:44:08.791Z, is an unrelated routine npm auto-update check.#673 (#674) shipped only the
[degenerate-turn]detector, described as "the groundwork for auto-retry" — the retry itself was never implemented. (The existing #371 fake-completion backstop detects a different shape, is opt-in/off by default, and only guards the first fetch, not loop rounds 2+.)Fix
In
src/loop/core.ts(runCompressLoop), after a round completes with nothing forwarded to the client yet (forwardedAny === false— true for these rounds on wires whose round>1 framing is suppressed, e.g. Responses) and the turn is a genuine silent thought, re-fetch once with an ephemeral continuation nudge. The nudge is appended only to the retry body — never committed tocoreMessages/session state, so it is neither persisted nor replayed.Guard rails:
degenerateRetried).sawThinking— surfaced on thedonestream event by all three adapters — so a legitimately empty/no-reasoning terminal turn is left untouched. Only the "silent thought" shape retries.Scoped to proxy mode automatically (the compress loop doesn't run in plugin mode).
Pre-flight
npm run typecheck✅npm test✅ 1431 pass / 0 fail / 2 skipped (incl. newtests/loop-degenerate-retry.test.ts: D1 one invisible retry w/ nudge, D2 one-shot bound)npm run build✅ (dist self-contained)