fix(P0): prevent thread.switchThread from clearing messages mid-stream
Trigger auto deployment for soc-langgraph / build-and-deploy (push) Failing after 30s
Deploy LangGraph UI to Azure Static Web Apps / build-and-deploy (push) Failing after 38s

When ensureThread() creates a new thread and calls setCurrentThreadId,
the useEffect fires thread.switchThread() again after doSubmit already
called it — wiping thread.messages mid-stream and showing the welcome
screen instead of AI replies.

Fix: add skipNextSwitchRef. When doSubmit creates a new thread and
manually calls thread.switchThread(), it sets the flag so the
subsequent useEffect is a no-op. Only needed for new threads (when
currentThreadId was null); existing-thread submits don't change
currentThreadId so the useEffect never fires.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
gongzhiyong
2026-04-15 02:48:15 +08:00
co-authored by Claude Opus 4.6
parent 902c8331be
commit b548ed4f19
+15 -2
View File
@@ -63,6 +63,8 @@ function App() {
type ConcurrentStatus = "idle" | "generating" | "stopping" | "cancelling";
const [concurrentStatus, setConcurrentStatus] = useState<ConcurrentStatus>("idle");
const wasStoppedRef = useRef(false);
// Skip the switchThread useEffect when doSubmit already called it manually
const skipNextSwitchRef = useRef(false);
interface SubmitPayload {
text: string;
@@ -95,8 +97,13 @@ function App() {
return () => window.removeEventListener("open-canvas", handler);
}, []);
// Clear error and stale stream state when thread switches
// Clear error and stale stream state when thread switches.
// Skip when doSubmit already called switchThread manually (to avoid clearing mid-stream).
useEffect(() => {
if (skipNextSwitchRef.current) {
skipNextSwitchRef.current = false;
return;
}
thread.switchThread(currentThreadId);
}, [currentThreadId]); // eslint-disable-line react-hooks/exhaustive-deps
@@ -210,7 +217,13 @@ function App() {
setConcurrentStatus("idle");
return;
}
thread.switchThread(activeThreadId);
// Only need to switchThread manually when a new thread was just created.
// For existing threads, currentThreadId didn't change so useEffect won't fire.
// Setting the skip flag prevents the useEffect from re-firing and clearing messages.
if (!currentThreadId) {
skipNextSwitchRef.current = true;
thread.switchThread(activeThreadId);
}
try { localStorage.removeItem(`draft_${activeThreadId}`); } catch { /* ignore */ }
updateThreadLastActive(activeThreadId);