From 02b9e1c0a3e670dd79d1b21c3c105786f5e544fc Mon Sep 17 00:00:00 2001 From: Theo Browne Date: Thu, 30 Jul 2026 07:07:28 -0700 Subject: [PATCH 1/2] fix(web): server updates no longer look like warnings The in-progress server update banner used amber warning chrome, a triangle icon, and green/blue stage colors, reading as an actionable alert when it is really a "one moment" wait. The step rail is now monochrome: done steps recede to gray, the active step is the only bright element and pulses with the duty-cycled status-pulse animation. Refreshing mid-update also stacked "Client and server versions differ" on "Failed to connect. Reconnecting..." because the in-memory update state was wiped. Reconnecting to a version-skewed server now collapses both into one calm "Reconnecting - it may be finishing an update" line, and the reconnect banner stays suppressed for the whole running update rather than only the resuming stage. Co-Authored-By: Claude Fable 5 --- apps/web/src/components/ChatView.tsx | 109 +++++++++++------- .../components/ServerUpdateAction.test.tsx | 13 ++- .../web/src/components/ServerUpdateAction.tsx | 96 +++++++-------- .../components/chat/ComposerBannerStack.tsx | 2 +- .../settings/ConnectionsSettings.tsx | 2 - 5 files changed, 120 insertions(+), 102 deletions(-) diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index ec85e4c4c18..d5de398a33d 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -1883,46 +1883,69 @@ function ChatViewContent(props: ChatViewProps) { ); const systemComposerBannerItems = useMemo(() => { const items: ComposerBannerStackItem[] = []; - const resumingServerUpdate = - serverUpdateState.status === "running" && serverUpdateState.stage === "resuming"; - if (activeEnvironmentUnavailableState && !resumingServerUpdate) { - const connection = activeEnvironmentUnavailableState.connection; - const isReconnecting = - connection.phase === "connecting" || connection.phase === "reconnecting"; - items.push({ - id: `environment-unavailable:${activeEnvironmentUnavailableState.environmentId}`, - variant: connection.phase === "error" ? "error" : "warning", - icon: , - title: `${activeEnvironmentUnavailableState.label}: ${connectionStatusTitle(connection)}`, - description: - connection.error ?? - "Reconnect this environment before sending messages or running actions.", - actions: ( - <> - - - - ), - }); + const updateRunning = serverUpdateState.status === "running"; + const unavailableConnection = activeEnvironmentUnavailableState?.connection ?? null; + const environmentReconnecting = + unavailableConnection !== null && + (unavailableConnection.phase === "connecting" || + unavailableConnection.phase === "reconnecting"); + // Reconnecting to a version-skewed server usually means the server is + // restarting mid-update (e.g. a refresh wiped the in-memory update + // state). Fold the reconnect and version banners into one calm line + // instead of stacking "Failed to connect" on "versions differ". + const reconnectingThroughVersionSkew = + !updateRunning && environmentReconnecting && versionMismatch !== null; + if (activeEnvironmentUnavailableState && unavailableConnection && !updateRunning) { + if (reconnectingThroughVersionSkew) { + items.push({ + id: `environment-unavailable:${activeEnvironmentUnavailableState.environmentId}`, + variant: "default", + icon: ( +