diff --git a/web/src/pages/ChatPage.tsx b/web/src/pages/ChatPage.tsx index 6bca795bde..a152d9c331 100644 --- a/web/src/pages/ChatPage.tsx +++ b/web/src/pages/ChatPage.tsx @@ -205,6 +205,16 @@ export default function ChatPage({ isActive = true }: { isActive?: boolean }) { useEffect(() => { setHasActivated((prev) => latchChatActivation(prev, isActive)); }, [isActive]); + + // Clear mobile-input tracking refs when the tab is hidden so stale state + // from a previous /chat visit doesn't cause the mobile-replacement logic + // to misfire on the next activation (#106403: repeated last character). + useEffect(() => { + if (!isActive) { + ptyInputLineRef.current = ""; + mobileReplacementInputUntilRef.current = 0; + } + }, [isActive]); const [searchParams, setSearchParams] = useSearchParams(); // Lazy-init: the missing-token check happens at construction so the effect // body doesn't have to setState (React 19's set-state-in-effect rule).