fix(session): show a message sent mid-turn in the transcript - #12
Open
Adam-Dalloul wants to merge 1 commit into
Open
Adam-Dalloul wants to merge 1 commit into
Adam-Dalloul wants to merge 1 commit into
Conversation
A message sent while the agent is still replying never appeared in the transcript. The client does not decode feedback_submitted at all, so the event falls into the AcpEvent .unknown catch-all and the handler drops it. The message only surfaces once the turn ends and the transcript reconciles with the server, which projects a mid-turn user_message_chunk as its own user turn. And because no user turn lands between the two halves of the reply, the answer to that message keeps streaming into the same assistant bubble, so two separate replies read as one run-on paragraph. Decode the event, and when the note is already delivered on submission (the native steering channel, where the agent has the text as a user message rather than as a check_user_feedback tool result), splice it into the live turn at the point it arrived. That closes the run the agent was writing and starts the reply to it in a fresh one, which is the same split the server's own projection makes, so the live view and a reload agree. It is idempotent by note id, since the submit is broadcast to every attached client including the sender, and it is ignored outside a running turn, where there is nothing to split and appending would graft the message onto a finished reply. The waiting shimmer moves to the tail of the turn, so interrupting the agent no longer leaves the transcript looking stalled. The turn's transcript is replaced wholesale by the server's copy when it settles, so nothing doubles on reload or on re-entering the session. The unreconciled fallback splits its snapshot the same way rather than folding a whole interrupted reply into one assistant turn. iOS itself still cannot send mid-turn: send() refuses while a turn is in flight and the compose button is Stop. What this fixes today is the cross-client case, a message sent from desktop or web while the phone is watching the same turn.
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.
A message sent while the agent is still replying never appears in the
transcript. It only shows up after the turn ends, once the transcript
reconciles with the server, and until then the answer to it keeps streaming
into the same assistant bubble, so two separate replies read as one run-on
paragraph.
The cause is that
feedback_submittedis never decoded: it falls into theAcpEvent.unknowncatch-all and the handler drops it. The server does recordthe message (it projects a mid-turn
user_message_chunkas its own user turn),which is why a reload shows it and the live view does not.
This decodes the event and, when the note is already
deliveredon submission(the native steering channel, where the agent has the text as a user message
rather than as a
check_user_feedbacktool result), splices it into the liveturn at the point it arrived. That closes the run the agent was writing and
starts the reply to it in a new one, which is the same split the server's own
projection makes. It is idempotent by note id, since the submit is broadcast to
every attached client including the sender, and ignored outside a running turn.
The turn's transcript is replaced by the server's copy once it settles, so
nothing doubles on reload or on re-entering the session.
This mirrors xintaofei/codeg#636, so the two clients behave the same way.
One boundary worth stating: iOS still cannot send mid-turn itself, since
send()refuses while a turn is in flight and the compose button is Stop. Whatthis fixes today is the cross-client case, a message sent from desktop or web
while the phone is watching the same turn.
Not compiled. I have no macOS or Xcode available, and the repo has no test
target and no CI, so this was verified by reading: every symbol and signature it
touches was checked against the tree, the new cases cover every exhaustive
switch over
AcpEvent,LiveSegmentandRenderPart, and the branch mergescleanly with the other open PRs.