Conversation
This comment has been minimized.
This comment has been minimized.
Three root causes of UI slowness during the primary user journey: 1. Every SSE token triggered a full React re-render (~20-50/sec during streaming). Added requestAnimationFrame-based event batching so multiple SSE events within a single frame are processed in one synchronous pass. React 18 batches all setState calls within the same callback, reducing re-renders from ~50/sec to ~60fps max. 2. sendMessage callback was recreated on every state change because it depended on state.threadId, state.runId, and state.status. Replaced with refs so the callback is stable across state changes, preventing cascading re-renders in child components. 3. Three overlapping polling intervals fired simultaneously during session startup: useSession (500-1000ms), workflow queue (2000ms), and message queue (2000ms). The latter two were redundant since useSession already polls aggressively during transitional states. Removed the duplicate intervals. 4. Initial prompt tracking effect had unnecessary deps (aguiState.messages.length, aguiState.status) that caused it to re-evaluate on every streamed message, even though it only updates a ref. Reduced to only depend on session.spec.initialPrompt. https://claude.ai/code/session_01P6sFQgvLjBHd6zuieQuzyz
- Consolidate three separate state-sync refs (threadId, runId, status) into a single stateSnapshotRef with proper typed status field - Add mountedRef guard to flushEventBuffer to prevent stale setState calls after unmount - Update React version reference in comment (18 → 18+) https://claude.ai/code/session_01P6sFQgvLjBHd6zuieQuzyz
bf90297 to
bfa0e8f
Compare
|
Reviewer: the guts of this change are here bfa0e8f#diff-8d67cd8823b6dd8fd3997ca62cf8edfb0a8b23b161edc0ab4ed9567dccdcd77fR53 |
Claude Code ReviewSummaryThis PR targets two frontend performance issues during AG-UI streaming sessions:
No backend, operator, or security-sensitive code is touched. No new Issues by Severity🚫 Blocker IssuesNone. 🔴 Critical IssuesNone. 🟡 Major IssuesNone. 🔵 Minor Issues1. Connection-check semantics changed in - if (!eventSourceRef.current) {
+ if (stateSnapshotRef.current.status !== 'connected') {These two conditions are not equivalent:
During the Suggestion: Consider 2. Trailing blank line introduced ( }),
))
+
+
try {Two blank lines where the rest of the file uses one. Trivial nit but breaks visual consistency. 3. No test coverage for the rAF batching path The new
This is not a blocker (the existing hook likely lacks tests already), but given this is a performance-critical path for the core streaming feature, a small set of Jest/RTL tests would significantly improve confidence. Positive HighlightsrAF batching is the right tool here. Collapsing N SSE events per animation frame into one React render pass is a well-established pattern and is particularly effective under React 18's automatic batching of synchronous
Removing redundant polling is the right call. The two removed Trimming the Unmount/disconnect cleanup is thorough. Recommendations
Overall this is a well-reasoned, focused performance PR with no security concerns and no violations of project standards. The rAF batching approach directly addresses the root cause of streaming jank. 🔍 View AI decision process (logs available for 90 days) 📋 View memory system files loaded (click to expand)What Amber Loaded for Code ReviewAmber automatically loaded these repository standards from the memory system:
Impact: This review used your repository's specific code quality standards, security patterns, and best practices from the memory system (PRs #359, #360) - not just generic code review guidelines. |
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Claude Code ReviewSummaryThis PR targets three root causes of UI jank during agent streaming: per-token React re-renders from raw SSE handling, a frequently-recreated Issues by Severity🚫 Blocker IssuesNone. 🔴 Critical IssuesNone. 🟡 Major Issues1. Removed polling depends on an undocumented invariant ( Both removed Recommendation: add a 🔵 Minor Issues2. useEffect(() => {
stateSnapshotRef.current = { threadId: ..., runId: ..., status: ... }
}, [state.threadId, state.runId, state.status])
3. Extra blank lines (cosmetic, Two extra blank lines snuck in — after the 4. No new tests for the rAF batching path The 5. The empty Positive Highlights
Recommendations
🔍 View AI decision process (logs available for 90 days) 📋 View memory system files loaded (click to expand)What Amber Loaded for Code ReviewAmber automatically loaded these repository standards from the memory system:
Impact: This review used your repository's specific code quality standards, security patterns, and best practices from the memory system (PRs #359, #360) - not just generic code review guidelines. |
No description provided.