Conversation
A message the user sends while a bridged tool runs arrives after the tool results in OpenCode's resume request. The parked bridge only consumed tool results, so the message was dropped and OpenCode then treated it as answered. Append its text to the last tool result resolved in that request, inside a system-reminder, so Claude reads it exactly once.
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.
In OpenCode you can send a message while the model is working. On
claude-code/*models those messages are silently lost whenever a tool is running.OpenCode puts a queued user message after the tool results in the next request. The proxy resumes the parked bridge using only the tool results, so the user message never reaches Claude. OpenCode still marks it as delivered, so the user thinks the model saw it. (A message sent while Claude is only generating text already works, because OpenCode starts a new turn for it.)
Fix: in the resume branch,
collectSteeringText()gathers the text of the user messages that come after the lasttoolmessage.withSteering()appends that text inside a<system-reminder>to the last tool result resolved in this request. Claude gets it as part of that tool result and can adjust right away. A later request has newer tool messages after the steer, so the same text is never delivered twice.We have run this locally with a real Claude Code CLI. A steer sent during
sleep 40("the secret word is PINEAPPLE") was ignored before the patch and used after it. In a run with three tool calls, it was delivered exactly once.Limits: text only (images in a queued message are not forwarded), and the message arrives when the current tool finishes, not mid-tool.
Test:
test/steering-regression.tsunit-testscollectSteeringText. It also parks a mock turn onbash, resumes with a tool result plus a trailing user message, and checks the tool result Claude receives contains the steer. A resume without a trailing message gets the plain result. Onmainthe steer is missing and the test fails.bun test/smoke.tsandtsc --noEmitpass.