fix(web): stop mid-turn resync from duplicating prior steps into a text blob - #1558
fix(web): stop mid-turn resync from duplicating prior steps into a text blob#1558wbxl2000 wants to merge 1 commit into
Conversation
🦋 Changeset detectedLatest commit: 80d059c The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 80d059ce8f
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| case 'turn.step.started': { | ||
| // New step → fresh accumulation. Completed steps live in the | ||
| // transcript; only the streaming step belongs in `in_flight_turn`. |
There was a problem hiding this comment.
Reset in-flight text when a step completes
Resetting only at the next turn.step.started leaves a race window after turn.step.completed: the completed step has already been persisted into the snapshot transcript, but get() still returns that same step's assistant_text / thinking_text until either another step starts or the turn ends. A reconnect or resync in that interval will still seed the just-finished step as in_flight_turn and duplicate it in the web UI; clear the accumulated text when the step completes as well.
Useful? React with 👍 / 👎.
|
Closing without merge: this fix will be implemented on a different kernel instead. The root-cause analysis and fix design are captured in a handover document. See the PR body for the full diagnosis (in-flight turn text accumulation across steps → mid-turn resync duplicates prior steps into a trailing blob). |
Related Issue
No issue — the problem was reported directly with an exported session (
session_e267cc76, protocol 1.4) plus screenshots of the web UI.Problem
While a multi-step agent turn is running, opening the session in kimi-web (or any WS reconnect / delta-gap resync) rebuilds the view from
GET /sessions/{sid}/snapshotplus the live event stream. In that state the turn rendered incorrectly: every prior step's text was concatenated into one giant Markdown blob appended after the structured history, and thinking blocks / tool cards stopped rendering for the rest of the turn.Root cause: the server's
InFlightTurnTrackeraccumulatesassistant_text/thinking_textfromturn.startedacross all steps of the turn. The snapshot returns that whole-turn text asin_flight_turn, and the web client (seedInFlight) seeds a single assistant message with it — duplicating content the snapshot transcript already carries as structured per-step messages. The seeded message merges into the turn and renders as the trailing blob (with ~90 KB of duplicated thinking folded behind a teaser).What changed
InFlightTurnTracker): reset the text/thinking accumulation at everyturn.step.started, soin_flight_turndescribes only the currently-streaming step; completed steps already live in the snapshot transcript. Delta-frame offsets become step-relative to match.agentEventProjector): reset the local delta-offset counters atturn.step.startedso alignment stays in step with the daemon. A missed step-initial delta now surfaces as a recoverable gap (triggers resync) instead of a silent permanent skip.in_flight_turn.assistant_text/thinking_text.Verified against the real session export: the seeded render now ends with
[thinking, text, tool:Read, thinking, text]— identical structure to the vis viewer — with no blob. Changeset included (@moonshot-ai/kimi-codepatch,web:entry).Checklist
gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update. (Internal rendering fix — no user-facing behavior to document.)