From aeed0dbb7d273bd43020be257329c6e1980a821c Mon Sep 17 00:00:00 2001 From: xlx1212 Date: Fri, 7 Aug 2026 05:17:42 +0800 Subject: [PATCH] fix(web-ui): prevent ACP session hydrate deadlock on re-switch When switching back to a previously-loaded ACP session, the UI showed a permanent 'loading saved session' overlay. The root cause was a deadlock in switchChatSession: ACP sessions never receive a history session open intent (filtered by isRunning), so shouldActivateBeforeHydrate was false. This meant hydration ran before activation, and with the default deferFullHistoryUntilActive=true, the stale-commit guard in FlowChatStore discarded the loaded turns (resetting to metadata-only). Then activation happened on an empty session, leaving the overlay stuck. Fix: pass deferFullHistoryUntilActive=false for ACP sessions so the hydrate commit is preserved even when activation hasn't happened yet. The subsequent switchSession call then activates a session that already has its loaded turns. Fixes #1038 --- .../src/flow_chat/services/flow-chat-manager/SessionModule.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/web-ui/src/flow_chat/services/flow-chat-manager/SessionModule.ts b/src/web-ui/src/flow_chat/services/flow-chat-manager/SessionModule.ts index 8ad55c599..ba1bf7d1f 100644 --- a/src/web-ui/src/flow_chat/services/flow-chat-manager/SessionModule.ts +++ b/src/web-ui/src/flow_chat/services/flow-chat-manager/SessionModule.ts @@ -31,6 +31,7 @@ import { resolveSessionTitle, } from '../../utils/sessionTitle'; import { buildCreateSessionRelationship } from '../../utils/sessionMetadata'; +import { isAcpFlowSession } from '../../utils/acpSession'; import { consumeRecentHistorySessionOpenIntent, hasRenderableSessionContent, @@ -701,6 +702,7 @@ export async function switchChatSession( await hydrateHistoricalSession(context, sessionId, true, { isRetryStillRelevant: () => switchRequestId === latestSwitchRequestId, retryActiveStaleReuse: shouldActivateBeforeHydrate, + deferFullHistoryUntilActive: !isAcpFlowSession(session), }); } catch { // The hydrate path already marks the session failed and notifies the user.