History

Reset stuck send phase after turns settle

- Keep the send timer alive while a send is active - Fallback-reset sendPhase when a turn settles after a missed transition

Julius Marminge committed 7 months ago

Commit 9a9be391 parent a60daa11 file · +15 −2Browse files

Unified · Split

apps/web/src/components/ChatView.tsx+15−2
@@ -2152,14 +2152,14 @@ export default function ChatView({ threadId }: ChatViewProps) { · 2151 unmodified lines
21522152 : "local";
21532153
21542154 useEffect(() => {
2155− if (phase !== "running") return;
2155+ if (phase !== "running" && sendPhase === "idle") return;
21562156 const timer = window.setInterval(() => {
21572157 setNowTick(Date.now());
21582158 }, 1000);
21592159 return () => {
21602160 window.clearInterval(timer);
21612161 };
2162− }, [phase]);
2162+ }, [phase, sendPhase]);
21632163
21642164 const beginSendPhase = useCallback((nextPhase: Exclude<SendPhase, "idle">) => {
21652165 setSendStartedAt((current) => current ?? new Date().toISOString());
@@ -2192,6 +2192,19 @@ export default function ChatView({ threadId }: ChatViewProps) { · 26 unmodified lines
21922192 sendPhase,
21932193 ]);
21942194
2195+ // Fallback: if the "running" phase transition was missed (e.g. due to React
2196+ // batching two snapshots, a WebSocket reconnect, or a very fast turn), the
2197+ // primary auto-reset above never fires and sendPhase stays stuck. Detect
2198+ // this by checking whether the turn has settled while sendPhase is still
2199+ // non-idle — the turn completing is a definitive signal that "sending" is
2200+ // over.
2201+ useEffect(() => {
2202+ if (sendPhase === "idle") return;
2203+ if (phase !== "running" && phase !== "connecting" && latestTurnSettled) {
2204+ resetSendPhase();
2205+ }
2206+ }, [latestTurnSettled, phase, resetSendPhase, sendPhase]);
2207+
21952208 useEffect(() => {
21962209 if (!activeThreadId) return;
21972210 const previous = terminalOpenByThreadRef.current[activeThreadId] ?? false;