From b04137f6bc94026ec3738deaaca329174db4dfd7 Mon Sep 17 00:00:00 2001 From: Gaurav Bhola Date: Thu, 2 Apr 2026 20:22:28 -0700 Subject: [PATCH] fix(web): address eighth-pass bugbot review issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - useSessionEvents: mux-active SSE cleanup now also resets pendingMembershipKeyRef and refreshingRef so the aborted fetch's .finally() handler cannot reschedule after unmount - DirectTerminal: add distinct "Disconnected" label and error-coloured dot for muxStatus "disconnected" (WebSocket constructor failure with no reconnect), instead of the misleading "Connecting…" shown for transient states Co-Authored-By: Claude Opus 4.6 --- packages/web/src/components/DirectTerminal.tsx | 12 +++++++++--- packages/web/src/hooks/useSessionEvents.ts | 5 ++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/web/src/components/DirectTerminal.tsx b/packages/web/src/components/DirectTerminal.tsx index afa6cba6e..c18f4a370 100644 --- a/packages/web/src/components/DirectTerminal.tsx +++ b/packages/web/src/components/DirectTerminal.tsx @@ -482,17 +482,23 @@ export function DirectTerminal({ const statusDotClass = displayStatus === "connected" ? "bg-[var(--color-status-ready)]" - : displayStatus === "error" + : displayStatus === "error" || displayStatus === "disconnected" ? "bg-[var(--color-status-error)]" : "bg-[var(--color-status-attention)] animate-[pulse_1.5s_ease-in-out_infinite]"; const statusText = - displayStatus === "connected" ? "Connected" : displayStatus === "error" ? (error ?? "Error") : "Connecting…"; + displayStatus === "connected" + ? "Connected" + : displayStatus === "error" + ? (error ?? "Error") + : displayStatus === "disconnected" + ? "Disconnected" + : "Connecting…"; const statusTextColor = displayStatus === "connected" ? "text-[var(--color-status-ready)]" - : displayStatus === "error" + : displayStatus === "error" || displayStatus === "disconnected" ? "text-[var(--color-status-error)]" : "text-[var(--color-text-tertiary)]"; diff --git a/packages/web/src/hooks/useSessionEvents.ts b/packages/web/src/hooks/useSessionEvents.ts index a90011aba..b1c8f8719 100644 --- a/packages/web/src/hooks/useSessionEvents.ts +++ b/packages/web/src/hooks/useSessionEvents.ts @@ -233,11 +233,14 @@ export function useSessionEvents( if (muxActive) { dispatch({ type: "setConnection", status: "connected" }); return () => { - // Clear any pending refresh timer so it doesn't fire after unmount + // Clear timer and reset all refresh state so the aborted fetch's + // .finally() handler doesn't reschedule after unmount. if (refreshTimerRef.current) { clearTimeout(refreshTimerRef.current); refreshTimerRef.current = null; } + pendingMembershipKeyRef.current = null; + refreshingRef.current = false; activeRefreshControllerRef.current?.abort(); activeRefreshControllerRef.current = null; };