From a901e90b597615660ab20a53859fe62e81b70623 Mon Sep 17 00:00:00 2001 From: Jerome Date: Thu, 12 Jun 2025 14:49:53 +0100 Subject: [PATCH] Fix agent loop UI bleeding between conversations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem When starting an agent loop in one conversation and switching to another, the "assistant thinking" UI would incorrectly appear in the second conversation, even though it was idle. ## Root Cause The `isLoading` state in ChatInterface was global/shared across all conversations. When conversation A started generating, `isLoading` was set to `true`. Switching to conversation B would still show the thinking UI because `isGenerating = agentLoopState?.isRunning || isLoading` evaluated to `true` due to the shared loading state. ## Solution - **Conversation-specific loading**: Changed from single `isLoading` boolean to `loadingConversations` Set tracking which conversations are loading - **Isolated state**: Each conversation now has independent loading state - **Proper cleanup**: Loading state is properly added/removed per conversation ## Technical Changes - Replaced `useState` with `useState>` - Updated `handleSendMessage` to add/remove conversation IDs from Set - Modified `isGenerating` calculation to check current conversation only ## User Experience - ✅ **Isolated UI state**: Thinking UI only appears for actually running conversations - ✅ **No cross-conversation interference**: Switching conversations shows correct state - ✅ **Maintained functionality**: All existing behavior preserved 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/components/ChatInterface.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/components/ChatInterface.tsx b/src/components/ChatInterface.tsx index 2117db1..cfdc43a 100644 --- a/src/components/ChatInterface.tsx +++ b/src/components/ChatInterface.tsx @@ -22,7 +22,7 @@ export function ChatInterface() { selectModel, isAuthenticated } = useInference(); - const [isLoading, setIsLoading] = useState(false); + const [loadingConversations, setLoadingConversations] = useState>(new Set()); const messagesEndRef = useRef(null); const activeConversation = activeConversationId ? getConversation(activeConversationId) : undefined; @@ -38,13 +38,17 @@ export function ChatInterface() { return; } - setIsLoading(true); + setLoadingConversations(prev => new Set(prev).add(activeConversationId)); try { await sendMessage(activeConversationId, content); } catch (error) { console.error('Failed to send message:', error); } finally { - setIsLoading(false); + setLoadingConversations(prev => { + const newSet = new Set(prev); + newSet.delete(activeConversationId); + return newSet; + }); } }; @@ -78,7 +82,8 @@ export function ChatInterface() { ); } - const isGenerating = agentLoopState?.isRunning || isLoading; + const isCurrentConversationLoading = activeConversationId ? loadingConversations.has(activeConversationId) : false; + const isGenerating = agentLoopState?.isRunning || isCurrentConversationLoading; return (