fix(ui): prevent UI freeze during context compaction#174
Merged
laynepenney merged 4 commits intomainfrom Jan 26, 2026
Merged
Conversation
- Add onCompaction callback to AgentOptions to notify UI when compaction starts/ends - Yield to event loop with setImmediate after callback to allow UI to render - Wire up callback in index.ts to show spinner and update Ink UI activity status - Fixes blocked key events during compaction by allowing event loop to process Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add debouncing (16ms/~60fps) to setStatus() to coalesce rapid updates - Add batching for appendToMessage() to reduce streaming re-renders - Add flush() method to immediately emit pending updates (useful for tests) - Update tests to account for debounced behavior This reduces re-renders during high-frequency updates (streaming, tool calls) which was causing key events to be dropped intermittently. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The spinner animation (updating every 120ms) was causing the entire InkApp component to re-render, which led to dropped key events. Users had to press keys 5-6 times before they registered. Fix: Extract spinner animation into a separate ActivityPanel component that manages its own state. This prevents the 120ms state updates from triggering full app re-renders: - Create ActivityPanel component with isolated spinner state - Move hasActiveProgress/spinnerFrame state into ActivityPanel - Remove spinner from statusLines (already shown in ActivityPanel) - Use simplified scroll info calculation that doesn't depend on spinner The parent InkApp now only re-renders when actual data changes, not every 120ms for spinner animation. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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.
Summary
onCompactioncallback toAgentOptionsto notify UI when compaction starts/endssetImmediateafter callback to allow UI to renderindex.tsto show spinner and update Ink UI activity statusProblem
The UI would freeze and key events would be blocked during context compaction because:
Solution
onCompaction?: (status: 'start' | 'end') => voidcallbackawait new Promise(resolve => setImmediate(resolve))to yield control back to the event loopTest plan
--context-window 4000to trigger compaction sooner🤖 Generated with Claude Code