From 4fd33a9329e0501f53575d466fdfe6477f1f0391 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Mon, 21 Jul 2025 05:46:57 +0000 Subject: [PATCH 1/2] fix: prevent auto-scroll when LLM finishes generating response Prevents unwanted auto-scroll when assistant messages are added (streaming completion) while preserving auto-scroll for user messages and streaming start. Fixes issue where users lose their reading position when LLM output completes. - Modified auto-scroll logic to check message role - Only auto-scroll for user messages and streaming start - Manual scroll-to-bottom button remains unchanged Fixes #162 Co-authored-by: Marks --- frontend/src/routes/_auth.chat.$chatId.tsx | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/frontend/src/routes/_auth.chat.$chatId.tsx b/frontend/src/routes/_auth.chat.$chatId.tsx index 793a0ae55..66138cd3d 100644 --- a/frontend/src/routes/_auth.chat.$chatId.tsx +++ b/frontend/src/routes/_auth.chat.$chatId.tsx @@ -327,7 +327,7 @@ function ChatComponent() { const isLoading = phase === "streaming"; const isPersisting = phase === "persisting"; - // Auto-scroll when new messages appear (user message or start of streaming) + // Auto-scroll when user messages are added or streaming starts const prevMessageCountRef = useRef(localChat.messages.length); const prevStreamingRef = useRef(false); @@ -336,8 +336,22 @@ function ChatComponent() { const hasNewMessage = messageCount > prevMessageCountRef.current; const justStartedStreaming = isLoading && !prevStreamingRef.current; - if (hasNewMessage || justStartedStreaming) { - // Always scroll for new user messages or when streaming starts + // Only auto-scroll for user messages or when streaming starts + // Don't auto-scroll when assistant messages are added (streaming completion) + let shouldAutoScroll = false; + + if (justStartedStreaming) { + // Always scroll when streaming starts + shouldAutoScroll = true; + } else if (hasNewMessage) { + // Only scroll for new user messages, not assistant messages + const latestMessage = localChat.messages[localChat.messages.length - 1]; + if (latestMessage?.role === "user") { + shouldAutoScroll = true; + } + } + + if (shouldAutoScroll) { const container = chatContainerRef.current; if (container) { requestAnimationFrame(() => { From 649ef32793dd9b84fde1289903b064227dbff580 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Tue, 5 Aug 2025 17:44:47 +0000 Subject: [PATCH 2/2] fix: prevent auto-scroll when streaming completes - Add justStoppedStreaming detection to prevent auto-scroll on assistant message completion - Track streaming state transitions more accurately - Fix issue where auto-scroll was triggered when LLM finished generating response Co-authored-by: Anthony --- frontend/src/routes/_auth.chat.$chatId.tsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/frontend/src/routes/_auth.chat.$chatId.tsx b/frontend/src/routes/_auth.chat.$chatId.tsx index 66138cd3d..4ab7e6ec6 100644 --- a/frontend/src/routes/_auth.chat.$chatId.tsx +++ b/frontend/src/routes/_auth.chat.$chatId.tsx @@ -330,11 +330,18 @@ function ChatComponent() { // Auto-scroll when user messages are added or streaming starts const prevMessageCountRef = useRef(localChat.messages.length); const prevStreamingRef = useRef(false); + const streamStartedRef = useRef(false); useEffect(() => { const messageCount = localChat.messages.length; const hasNewMessage = messageCount > prevMessageCountRef.current; const justStartedStreaming = isLoading && !prevStreamingRef.current; + const justStoppedStreaming = !isLoading && prevStreamingRef.current; + + // Track when streaming actually starts + if (justStartedStreaming) { + streamStartedRef.current = true; + } // Only auto-scroll for user messages or when streaming starts // Don't auto-scroll when assistant messages are added (streaming completion) @@ -343,14 +350,20 @@ function ChatComponent() { if (justStartedStreaming) { // Always scroll when streaming starts shouldAutoScroll = true; - } else if (hasNewMessage) { + } else if (hasNewMessage && !justStoppedStreaming) { // Only scroll for new user messages, not assistant messages + // Also don't scroll if we just stopped streaming (assistant message completion) const latestMessage = localChat.messages[localChat.messages.length - 1]; if (latestMessage?.role === "user") { shouldAutoScroll = true; } } + // Reset stream tracking when streaming stops + if (justStoppedStreaming) { + streamStartedRef.current = false; + } + if (shouldAutoScroll) { const container = chatContainerRef.current; if (container) { @@ -365,7 +378,7 @@ function ChatComponent() { prevMessageCountRef.current = messageCount; prevStreamingRef.current = isLoading; - }, [localChat.messages.length, isLoading]); + }, [localChat.messages.length, isLoading, localChat.messages]); const sendMessage = useCallback( async (