From 0b372986116cbd73f5e96b861d8b7a1348a1282e Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 31 Jan 2026 12:48:51 +0000 Subject: [PATCH] fix: resolve new conversation message send bug Two bugs were causing the first message in a new conversation to fail: 1. Session not found: sendMessage threw "No session found" because the session was only created in useEffect (which runs after sendMessage). Fix: Auto-open session in sendMessage if one doesn't exist, using the conversation's provider/model from Dexie. 2. Pending message cleared: useEffect that resets state on conversationId change also ran when creating a new conversation, clearing the pendingUserMessage we just set. Fix: Track isCreatingConversationRef and skip the reset when we're in the middle of creating a conversation. https://claude.ai/code/session_01HqtD9R33oqfB14Gu1V5wHC --- src/components/AIViewer.tsx | 19 +++++++++++++++++-- src/services/llm/session-manager.ts | 22 ++++++++++++++-------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/components/AIViewer.tsx b/src/components/AIViewer.tsx index 6639d70..52d6613 100644 --- a/src/components/AIViewer.tsx +++ b/src/components/AIViewer.tsx @@ -263,8 +263,20 @@ function ChatPanel({ const messagesEndRef = useRef(null); const textareaRef = useRef(null); - // Reset input when switching conversations + // Track if we're in the middle of creating a new conversation + // This prevents the reset useEffect from clearing pendingUserMessage + const isCreatingConversationRef = useRef(false); + + // Reset input when switching conversations (but not when creating new one) useEffect(() => { + if (isCreatingConversationRef.current) { + // We just created this conversation - don't reset pendingUserMessage + isCreatingConversationRef.current = false; + textareaRef.current?.focus(); + return; + } + + // User switched to a different conversation - reset everything setInput(""); setPendingUserMessage(null); textareaRef.current?.focus(); @@ -302,14 +314,17 @@ function ChatPanel({ providerInstanceId, modelId, ); + // Mark that we're creating - prevents useEffect from clearing pendingUserMessage + isCreatingConversationRef.current = true; onConversationCreated(activeConversationId); } - // Send via session manager (handles everything) + // Send via session manager (auto-opens session if needed) await sendMessage(activeConversationId, userContent); } catch (err) { console.error("Failed to send message:", err); setPendingUserMessage(null); + isCreatingConversationRef.current = false; } }; diff --git a/src/services/llm/session-manager.ts b/src/services/llm/session-manager.ts index b254f1d..6c59ab8 100644 --- a/src/services/llm/session-manager.ts +++ b/src/services/llm/session-manager.ts @@ -258,23 +258,29 @@ class ChatSessionManager { /** * Send a message and stream the response. * This is the main entry point for chat interactions. + * Auto-opens a session if one doesn't exist. */ async sendMessage(conversationId: string, content: string): Promise { - const session = this.getSession(conversationId); + // Get conversation from Dexie first (we need it for auto-session and message) + const conversation = await db.llmConversations.get(conversationId); + if (!conversation) { + throw new Error(`Conversation ${conversationId} not found`); + } + + // Auto-open session if it doesn't exist + let session = this.getSession(conversationId); if (!session) { - throw new Error(`No session found for conversation ${conversationId}`); + session = this.openSession( + conversationId, + conversation.providerInstanceId, + conversation.modelId, + ); } if (session.isLoading) { throw new Error("Session is already generating a response"); } - // Get conversation from Dexie - const conversation = await db.llmConversations.get(conversationId); - if (!conversation) { - throw new Error(`Conversation ${conversationId} not found`); - } - // Create user message const userMessage: LLMMessage = { id: crypto.randomUUID(),