Skip to content

revert(vscode-ide-companion): undo #3450 split-stream timestamp sharing#3573

Merged
qqqys merged 1 commit into
QwenLM:mainfrom
qqqys:fix/chat-order
Apr 24, 2026
Merged

revert(vscode-ide-companion): undo #3450 split-stream timestamp sharing#3573
qqqys merged 1 commit into
QwenLM:mainfrom
qqqys:fix/chat-order

Conversation

@qqqys

@qqqys qqqys commented Apr 24, 2026

Copy link
Copy Markdown
Collaborator

TLDR

Roll back #3450 byte-for-byte on useMessageHandling.ts. #3450 tried to fix #3273 (a later user message sorting between two segments of the previous assistant turn) by pinning every split segment to the same turn-start timestamp, but that strategy conflicts with the tool-call timeline: tool calls carry their own arrival timestamp (strictly greater than the turn-start timestamp), so after #3450 every tool call sorts after both assistant segments instead of between them. The resulting "tool call jumped to the end" symptom is what users are currently reporting. Revert unblocks that regression; two focused tests pin the two conflicting invariants so the next fix has a clear target.

Dive Deeper

The webview (App.tsx) merges text messages (useMessageHandling.messages) and tool-call cards (useToolCalls map) into a single array and sorts by timestamp for rendering. Three producers write into that sort key:

  1. Assistant seg1 — created by startStreaming(T_stream) using the extension-side Date.now() that rides on the streamStart message.
  2. Tool call — created by useToolCalls.resolveTimestamp, which takes the ACP _meta.timestamp when present, otherwise the webview's Date.now() at event-arrival time. Always ≥ T_stream.
  3. Assistant seg2 (the one created after a breakAssistantSegment()) — before fix(vscode-ide-companion): preserve split stream message ordering #3450, created with the webview's Date.now() at chunk-arrival time; after fix(vscode-ide-companion): preserve split stream message ordering #3450, re-uses T_stream.

#3273 — under React batching on Linux, Date.now() inside the setMessages reducer of appendStreamChunk can be evaluated later than the next-turn user message was pushed. That produces seg2.ts > nextUser.ts, and the sort wedges the new user bubble between seg1 and seg2.

#3450 — reused T_stream for seg2 so seg1.ts == seg2.ts; since the next user message's timestamp is always > T_stream, it can no longer slip between segments. This closed #3273 but locked every seg2 at T_stream, which is less than any tool call in the same turn — so tool-call cards are now appended at the bottom of the turn instead of between the two segments.

The two invariants are genuinely opposed under a single-timestamp sort:

Invariant needed for… Constraint
Tool-call interleave (today's bug) seg1.ts < toolCall.ts < seg2.ts
#3273 (yesterday's bug) all segs of turn N < any event of turn N+1

Satisfying both requires a monotonic sequence number shared across producers (messages, tool calls, plan cards), not just smarter timestamps. That is out of scope for this revert — the goal here is to restore the more-visible tool-call ordering and pin the invariants down in tests so the next PR can be judged against both at once.

This PR touches exactly two files:

  • useMessageHandling.ts — identical to cfe142e9a^ (byte-for-byte).
  • useMessageHandling.test.tsx — rewritten with two focused cases (see Reviewer Test Plan).

Reviewer Test Plan

  1. In packages/vscode-ide-companion, run npm run build.
  2. npx vitest run src/webview/hooks — all 5 test files / 10 cases green, including the two new ones in useMessageHandling.test.tsx:
    • assigns the second assistant segment a newer timestamp so a tool call can sort between the two segments — a normal it, passes today.
    • keeps every assistant segment of a turn before a user message that was sent between segments (#3273) — marked it.fails and documents the known regression; will flip to a plain it once the monotonic-sequence fix lands.
  3. Open the VS Code companion and send a prompt that emits tool calls mid-reply (e.g. "read file X and summarize"). Confirm the tool-call cards now render between the two assistant text segments instead of being appended after them.
  4. Optional stress: send a follow-up user question quickly after a tool-heavy turn; Chat messages are displayed in the wrong order - when I ask a question, it appears ABOVE my previous answer, instead of below it. #3273 may reappear until the proper fix lands — this is the expected trade-off documented by the it.fails test.

Testing Matrix

🍏 🪟 🐧
npm run
npx
Docker - - -
Podman - - -
Seatbelt - - -

Linked issues / bugs

Reverts #3450. Re-opens #3273 as a known regression pinned by the it.fails test; the next PR should close it together with the tool-call interleave invariant.

… sharing

QwenLM#3450 pinned every assistant/thinking segment in a streamed turn to the
same turn-start timestamp so a later user message could not be sorted
between two segments of the previous turn (QwenLM#3273). That fix turned out
to conflict with the tool-call timeline: tool calls carry their own
arrival timestamp, which is strictly greater than the turn-start
timestamp, so after QwenLM#3450 every tool call sorted AFTER both assistant
segments instead of between them — the exact 'tool call jumped to the
end' ordering bug users are now reporting.

The two bugs pull the sort key in opposite directions and cannot both
be satisfied by a single timestamp strategy. Roll QwenLM#3450 back byte-for-
byte on useMessageHandling.ts so the tool-call ordering regression is
fixed immediately; replace the test file with two focused cases that
pin the conflicting invariants so the next fix (likely a monotonic
sequence key shared across messages and tool calls) has a clear
target:

  - tool-call interleave test (passes today): a tool call that arrives
    between two assistant segments must sort strictly between them.
  - QwenLM#3273 regression test (it.fails today): all assistant segments of
    one turn must sort before a user message sent during the turn.
    Flipped to a normal it() once the proper fix lands.

Refs: QwenLM#3273, QwenLM#3450

Co-Authored-By: Qwen-Coder <noreply@qwenlm.ai>
@qqqys qqqys requested a review from yiliang114 April 24, 2026 03:27

@yiliang114 yiliang114 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

assistantIdx < next.length
? next[assistantIdx].timestamp
: (currentStreamTimestampRef.current ?? Date.now());
: Date.now();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this fallback changed from currentStreamTimestampRef.current ?? Date.now() to plain Date.now(). The primary path (reading from next[assistantIdx].timestamp) should always be taken during active streaming so this is effectively a no-op — just flagging it so it's on the radar when implementing the monotonic-sequence fix, since the thinking timestamp derivation will need to participate in that scheme too.

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found. LGTM! ✅ — gpt-5.5 via Qwen Code /review

@qqqys qqqys merged commit 2815a2f into QwenLM:main Apr 24, 2026
13 checks passed
xaelistic pushed a commit to xaelistic/qwen-code that referenced this pull request Jun 7, 2026
… sharing (QwenLM#3573)

QwenLM#3450 pinned every assistant/thinking segment in a streamed turn to the
same turn-start timestamp so a later user message could not be sorted
between two segments of the previous turn (QwenLM#3273). That fix turned out
to conflict with the tool-call timeline: tool calls carry their own
arrival timestamp, which is strictly greater than the turn-start
timestamp, so after QwenLM#3450 every tool call sorted AFTER both assistant
segments instead of between them — the exact 'tool call jumped to the
end' ordering bug users are now reporting.

The two bugs pull the sort key in opposite directions and cannot both
be satisfied by a single timestamp strategy. Roll QwenLM#3450 back byte-for-
byte on useMessageHandling.ts so the tool-call ordering regression is
fixed immediately; replace the test file with two focused cases that
pin the conflicting invariants so the next fix (likely a monotonic
sequence key shared across messages and tool calls) has a clear
target:

  - tool-call interleave test (passes today): a tool call that arrives
    between two assistant segments must sort strictly between them.
  - QwenLM#3273 regression test (it.fails today): all assistant segments of
    one turn must sort before a user message sent during the turn.
    Flipped to a normal it() once the proper fix lands.

Refs: QwenLM#3273, QwenLM#3450

Co-authored-by: Qwen-Coder <noreply@qwenlm.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Chat messages are displayed in the wrong order - when I ask a question, it appears ABOVE my previous answer, instead of below it.

3 participants