Uh oh!
There was an error while loading. Please reload this page.
fix(opencode): stop repeated empty tool loops - #37110
Conversation
The following comment was made by an LLM, it may be inaccurate: Found a potential duplicate: Related PR: #37109 - This PR appears to address the same issue of preventing repeated tool loops when there's no meaningful progress. Both PRs reference issue #31942 and deal with guarding against consecutive empty/no-match tool outcomes. You may want to review whether these are addressing the same problem from different angles or if one should be closed in favor of the other. |
Automated PR Cleanup Thank you for contributing to opencode. Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions. This PR was closed because it matched the following cleanup criteria:
PRs created within the last month are not affected by this cleanup. If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate. Thanks again for taking the time to contribute. |
Issue for this PR
Closes#31942
Type of change
What does this PR do?
Stops sequential discovery-tool loops after three consecutive empty/no-match outcomes, even when the model changes the query each time. The guard checks settled session history before the next provider turn, so it works across assistant messages instead of only within one processor stream.
The stop is durable and user-visible, resets after meaningful output, another tool, or new user input, and does not classify empty mutation-tool payloads as no progress. Exact repeated tool errors are also bounded. This keeps the existing exact-input
doom_looppermission as an earlier complementary warning.This builds on the conservative empty-result handling explored in #31998, but moves detection to the continuation boundary so it covers the production cross-turn loop shape. The detector accepts a threshold and defaults to 3; user-facing threshold policy remains tracked separately in #23531.
How did you verify your code works?
cd packages/core && bun test test/session-tool-loop.test.ts test/session-runner.test.ts(88 passed)cd packages/opencode && bun test test/session/prompt.test.ts test/session/processor-effect.test.ts(72 passed, 1 pre-existing skip)bun typecheck(30 package tasks passed)The regressions use three separate provider turns with varied MCP prefixes, assert that a queued fourth response is not consumed, verify replay durability and inert resume behavior, and confirm that fresh user input can continue the session.
Screenshots / recordings
N/A (runtime-only change)
Checklist