Conversation
Update zod dependency to ^4.3.6 and fix config.ts to use explicit fully-populated default objects for nested schemas, required by Zod v4's changed .default() semantics (short-circuits instead of parsing defaults).
…and sluggishness Three bugs identified and fixed: 1. Auto-recovery infinite loop (CRITICAL): When a context overflow error triggered auto-recovery via session.prompt(), if the recovery itself also overflowed, a new session.error fired with no re-entrancy guard, creating an infinite loop of distill+prompt calls (2+ LLM calls per cycle). Fix: add recoveringSessions Set — second overflow for the same session bails out immediately. 2. Curator fires on every session.idle (HIGH): The condition used 'onIdle || turnsSinceCuration >= afterTurns'. Since onIdle defaults to true, the || short-circuits and afterTurns (default: 10) is never checked. The curator fired an LLM worker request after every single agent turn. Fix: change || to && — curate on idle only when enough turns have accumulated. 3. shouldSkip lists all sessions on every unknown message (MEDIUM): When session.get() failed (common with short IDs from message events), the fallback called session.list() fetching ALL sessions on every unknown message event. Fix: remove session.list() fallback, cache sessions as known-good after first check. Worker sessions are already caught by isWorkerSession(). Symptoms these fixes address: - Upstream rate limiting from excessive LLM calls - Slower LLM interactions (curator competing for rate limit budget) - Many 'error' sounds in TUI (each failed recovery wrote to stderr) - 'Prompt too long' errors visible in TUI (recovery loop) - Overall sluggish OpenCode server behavior
…und-requests # Conflicts: # AGENTS.md
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.
Problem
Users reported multiple symptoms pointing to excessive background LLM requests:
Root Causes & Fixes
Bug 1: Auto-Recovery Infinite Loop (CRITICAL)
When a context overflow (
prompt too long) triggered auto-recovery viasession.prompt(), if the recovery itself also overflowed, a newsession.errorfired with no re-entrancy guard, creating an infinite loop:Each cycle fired 2+ LLM calls, repeating until rate-limited.
Fix: Add
recoveringSessionsSet. If a session is already recovering when a second overflow arrives, bail out immediately (forceMinLayer is still persisted for the user's next manual message).Bug 2: Curator Fires on Every
session.idle(HIGH)The condition used
onIdle || turnsSinceCuration >= afterTurns. SinceonIdledefaults totrue, the||short-circuits —afterTurns(default: 10) was never evaluated. The curator fired an LLM worker request after every single agent turn.Fix: Change
||to&&— curate on idle only when enough turns have accumulated.Bug 3:
shouldSkipLists All Sessions on Every Unknown Message (MEDIUM)When
session.get()failed (common with short IDs from message events), the fallback calledsession.list()fetching ALL sessions on every unknown message event.Fix: Remove
session.list()fallback, cache sessions as known-good after first check. Worker sessions are already caught byisWorkerSession(). Accept the tradeoff: short-ID child sessions won't be skipped, but a few extra temporal messages from eval are harmless.Testing
test/index.test.tscovering:isContextOverflowdetection for all error message formatsbuildRecoveryMessagewith and without summariesturnsSinceCuration < afterTurnsshouldSkip: nosession.list()fallback, sessions cached after first check