Skip to content

Fix thinking blocks rendering below streaming text due to SSE race condition#456

Merged
AnthonyRonning merged 1 commit intomasterfrom
devin/1772688876-fix-thinking-block-ordering
Mar 5, 2026
Merged

Fix thinking blocks rendering below streaming text due to SSE race condition#456
AnthonyRonning merged 1 commit intomasterfrom
devin/1772688876-fix-thinking-block-ordering

Conversation

@devin-ai-integration
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot commented Mar 5, 2026

Summary

Fixes a race condition where thinking/reasoning blocks would occasionally render below the "..." loading dots or streamed text in desktop and mobile Tauri builds. This happened because SSE events can arrive out of order — the assistant message response.output_item.added event sometimes arrived before the reasoning response.output_item.added event, and mergeMessagesById preserves insertion order.

The fix sorts items within each assistant group at render time so that reasoning items always appear first, followed by tool-related items (web search, function calls), with assistant message content last. This is done in the groupedMessages useMemo computation inside MessageList.

Review & Testing Checklist for Human

  • Test with a thinking model (e.g., one that produces reasoning items like Kimi K2) on desktop Tauri — verify the thinking block always appears above the streaming text, not below the "..." dots
  • Test on mobile Tauri build (iOS/Android) since the bug was also reported there
  • Test non-thinking flows — verify tool calls, web search results, and regular messages still render in the expected order (the sort is stable, so same-priority items keep their original order)
  • Verify the assistantItemSortOrder function being defined outside the useMemo doesn't cause unnecessary re-computation (it's a pure function with no captured state, so it should be fine)

Notes


Open with Devin

Summary by CodeRabbit

Bug Fixes

  • Improved ordering of assistant-generated content in streaming conversations. Reasoning, tool calls, and tool outputs now render in the correct sequence, enhancing reliability when items arrive out of order during real-time interactions. This ensures more consistent and predictable display of assistant messages and related content elements.

…ndition

Sort assistant group items so reasoning items always appear before message
items, regardless of the order SSE events arrive. This prevents the race
condition where the assistant message 'added' event arrives before the
reasoning 'added' event, causing thinking blocks to render below the '...'
loading dots or streamed text.

Co-Authored-By: tony@opensecret.cloud <TonyGiorgio@protonmail.com>
@devin-ai-integration
Copy link
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@cloudflare-workers-and-pages
Copy link

Deploying maple with  Cloudflare Pages  Cloudflare Pages

Latest commit: e7e31ee
Status: ✅  Deploy successful!
Preview URL: https://871e1912.maple-ca8.pages.dev
Branch Preview URL: https://devin-1772688876-fix-thinkin.maple-ca8.pages.dev

View logs

Copy link
Contributor Author

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

@AnthonyRonning
Copy link
Contributor

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Mar 5, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link

coderabbitai bot commented Mar 5, 2026

📝 Walkthrough

Walkthrough

The change adds deterministic sorting for assistant-related items in the UnifiedChat component, establishing a fixed order where reasoning items render first, followed by tool calls and outputs, then messages. This sort is applied when processing assistant item groups during streaming, improving resilience to out-of-order events.

Changes

Cohort / File(s) Summary
Assistant Item Sorting
frontend/src/components/UnifiedChat.tsx
Introduces assistantItemSortOrder helper function assigning priority levels to item types (reasoning: 0, tool calls/outputs: 1, messages: 2), and applies deterministic sorting when flushing and finalizing assistant item groups.
Dependencies
package.json
Package dependency or version updates supporting frontend changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • Tooluse UI #265: Modifies assistant/tool-related item rendering and ordering in the same UnifiedChat component to handle streaming and tool-call sequencing.

Poem

🐰 A rabbit hops through streaming streams,
Ordering items by sorting dreams,
Reasoning first, then tools align,
Messages follow in perfect line,
No more chaos, the flow's divine!

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: fixing thinking blocks rendering below streaming text due to an SSE race condition, which is the core objective of the PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch devin/1772688876-fix-thinking-block-ordering

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/src/components/UnifiedChat.tsx`:
- Around line 525-530: The group ID is taken from the unsorted
currentAssistantItems[0].id which can differ from the first item after sorting;
update both places where you build the group object (the block using items:
[...currentAssistantItems].sort((a,b)=>assistantItemSortOrder(a)-assistantItemSortOrder(b))
and the later, identical block) to compute the sorted array into a local
variable (e.g., const sorted = [...currentAssistantItems].sort(...)) and use
sorted[0].id for the group id (`assistant-${sorted[0].id}`) and sorted for
items, then clear currentAssistantItems as before.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 10830f14-d847-4e6c-bc41-9debd908742c

📥 Commits

Reviewing files that changed from the base of the PR and between 1e7d24d and e7e31ee.

📒 Files selected for processing (1)
  • frontend/src/components/UnifiedChat.tsx

Comment on lines +525 to 530
items: [...currentAssistantItems].sort(
(a, b) => assistantItemSortOrder(a) - assistantItemSortOrder(b)
),
id: `assistant-${currentAssistantItems[0].id}`
});
currentAssistantItems = [];
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Group ID derived from unsorted array may cause key instability.

The sort result is used for items:, but currentAssistantItems[0].id (lines 528 and 550) references the original unsorted array. If SSE events arrive out of order (the exact scenario this PR fixes), the first item before sorting could be a message item, while after sorting it becomes a reasoning item.

This means the group's React key (assistant-${id}) may reference different item types across renders, potentially causing unnecessary re-renders or subtle reconciliation issues.

Consider using the sorted array's first item for the ID:

🔧 Suggested fix
           if (currentAssistantItems.length > 0) {
+            const sortedItems = [...currentAssistantItems].sort(
+              (a, b) => assistantItemSortOrder(a) - assistantItemSortOrder(b)
+            );
             groups.push({
               type: "assistant",
-              items: [...currentAssistantItems].sort(
-                (a, b) => assistantItemSortOrder(a) - assistantItemSortOrder(b)
-              ),
-              id: `assistant-${currentAssistantItems[0].id}`
+              items: sortedItems,
+              id: `assistant-${sortedItems[0].id}`
             });
             currentAssistantItems = [];
           }

Apply the same pattern for lines 547-551.

Also applies to: 547-551

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/components/UnifiedChat.tsx` around lines 525 - 530, The group ID
is taken from the unsorted currentAssistantItems[0].id which can differ from the
first item after sorting; update both places where you build the group object
(the block using items:
[...currentAssistantItems].sort((a,b)=>assistantItemSortOrder(a)-assistantItemSortOrder(b))
and the later, identical block) to compute the sorted array into a local
variable (e.g., const sorted = [...currentAssistantItems].sort(...)) and use
sorted[0].id for the group id (`assistant-${sorted[0].id}`) and sorted for
items, then clear currentAssistantItems as before.

@AnthonyRonning AnthonyRonning merged commit 8628389 into master Mar 5, 2026
14 checks passed
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.

1 participant