From 2ad1313cb48cb491c4426af88a685716b19b2323 Mon Sep 17 00:00:00 2001 From: Ammar Date: Sat, 7 Mar 2026 11:36:38 -0600 Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=96=20fix:=20soften=20delayed-start=20?= =?UTF-8?q?retry=20banner?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid claiming the stream was interrupted while the first response is still stuck in pre-stream startup. Long SSH init hooks can legitimately delay stream-start even when the response will eventually begin, so the RetryBarrier now uses delayed-start copy for that state and includes a regression test. --- _Generated with `mux` • Model: `openai:gpt-5.4` • Thinking: `xhigh` • Cost: `$2.42`_ --- .../ChatBarrier/RetryBarrier.test.tsx | 20 +++++++++++++++++++ .../Messages/ChatBarrier/RetryBarrier.tsx | 14 ++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/browser/features/Messages/ChatBarrier/RetryBarrier.test.tsx b/src/browser/features/Messages/ChatBarrier/RetryBarrier.test.tsx index cdba1aad97..05f30cb212 100644 --- a/src/browser/features/Messages/ChatBarrier/RetryBarrier.test.tsx +++ b/src/browser/features/Messages/ChatBarrier/RetryBarrier.test.tsx @@ -136,6 +136,26 @@ describe("RetryBarrier", () => { globalThis.document = undefined as unknown as Document; }); + test("uses delayed-start copy while the first response is still starting", () => { + currentWorkspaceState = createWorkspaceState({ + isStreamStarting: true, + messages: [ + { + type: "user", + id: "user-1", + historyId: "user-1", + content: "Hello", + historySequence: 1, + }, + ], + }); + + const view = render(); + + expect(view.getByText("Response startup is taking longer than expected")).toBeTruthy(); + expect(view.queryByText("Stream interrupted")).toBeNull(); + }); + test("shows error details when manual resume fails before stream events", async () => { resumeStreamResult = { success: false, diff --git a/src/browser/features/Messages/ChatBarrier/RetryBarrier.tsx b/src/browser/features/Messages/ChatBarrier/RetryBarrier.tsx index 5da7b154d4..0a1f5e5ff1 100644 --- a/src/browser/features/Messages/ChatBarrier/RetryBarrier.tsx +++ b/src/browser/features/Messages/ChatBarrier/RetryBarrier.tsx @@ -242,11 +242,23 @@ export const RetryBarrier: React.FC = (props) => { const lastMessage = getLastNonDecorativeMessage(workspaceState.messages); const lastStreamError = lastMessage?.type === "stream-error" ? lastMessage : null; const interruptionReason = lastStreamError?.errorType === "rate_limit" ? "Rate limited" : null; + const isWaitingForInitialResponse = + lastMessage?.type === "user" && workspaceState.isStreamStarting; let statusIcon: React.ReactNode = (