From d73f6d6a2984e2534f39d3d462242113541e09d7 Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 24 Mar 2026 14:29:55 +0800 Subject: [PATCH] fix: persist agent scene generation pending state --- .../agents/AgentGenerationWorkspaceDarkV2.tsx | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/components/agents/AgentGenerationWorkspaceDarkV2.tsx b/components/agents/AgentGenerationWorkspaceDarkV2.tsx index 72246a2f6..ac951876a 100644 --- a/components/agents/AgentGenerationWorkspaceDarkV2.tsx +++ b/components/agents/AgentGenerationWorkspaceDarkV2.tsx @@ -527,9 +527,76 @@ function getReplacementCardStatusMeta(status: ReplacementCardStatus) { } interface LocalGenerationPendingState { + chatId: string; modeType: AgentGenerationResultModeType; expectedCount: number; userTurnCountAtStart: number; + timestamp: number; +} + +const AGENT_PENDING_GENERATION_STORAGE_KEY = "ai-chatbot-agent-pending-generations"; +const AGENT_PENDING_GENERATION_EXPIRY_MS = 30 * 60 * 1000; + +function getStoredAgentPendingGenerations(): LocalGenerationPendingState[] { + if (typeof window === "undefined") { + return []; + } + + try { + const raw = window.localStorage.getItem(AGENT_PENDING_GENERATION_STORAGE_KEY); + if (!raw) { + return []; + } + + const now = Date.now(); + const parsed = JSON.parse(raw); + if (!Array.isArray(parsed)) { + return []; + } + + return parsed.filter((item) => { + if (!item || typeof item !== "object") { + return false; + } + const record = item as Record; + const chatId = String(record.chatId || "").trim(); + const modeType = String(record.modeType || "").trim(); + const expectedCount = Number(record.expectedCount); + const userTurnCountAtStart = Number(record.userTurnCountAtStart); + const timestamp = Number(record.timestamp); + return ( + Boolean(chatId) && + (modeType === "scene_generation" || + modeType === "detail_replacement" || + modeType === "sku_replacement") && + Number.isFinite(expectedCount) && + expectedCount > 0 && + Number.isFinite(userTurnCountAtStart) && + Number.isFinite(timestamp) && + now - timestamp < AGENT_PENDING_GENERATION_EXPIRY_MS + ); + }) as LocalGenerationPendingState[]; + } catch { + return []; + } +} + +function saveStoredAgentPendingGenerations(items: LocalGenerationPendingState[]) { + if (typeof window === "undefined") { + return; + } + + try { + window.localStorage.setItem( + AGENT_PENDING_GENERATION_STORAGE_KEY, + JSON.stringify(items) + ); + } catch (error) { + console.warn( + "[AgentGenerationWorkspaceDarkV2] Failed to persist pending generation state:", + error + ); + } } function AnimatedGenerationPlaceholderCard(params: { @@ -693,6 +760,27 @@ export function AgentGenerationWorkspaceDarkV2({ const [pendingGeneration, setPendingGeneration] = useState(null); + useEffect(() => { + const restored = getStoredAgentPendingGenerations().find( + (item) => item.chatId === chatId + ); + if (!restored) { + return; + } + + setPendingGeneration((current) => current || restored); + }, [chatId]); + + useEffect(() => { + const allItems = getStoredAgentPendingGenerations().filter( + (item) => item.chatId !== chatId + ); + if (pendingGeneration) { + allItems.push(pendingGeneration); + } + saveStoredAgentPendingGenerations(allItems); + }, [chatId, pendingGeneration]); + const { data: historyData } = useSWR<{ messages: ChatMessage[] }>( rawChatId ? `/api/messages?chatId=${rawChatId}` : null, fetcher, @@ -1613,6 +1701,10 @@ export function AgentGenerationWorkspaceDarkV2({ return; } + if (pendingGeneration.modeType === "scene_generation") { + return; + } + if (!hasAssistantFailureAfterLastUser) { return; } @@ -1911,6 +2003,7 @@ export function AgentGenerationWorkspaceDarkV2({ setActiveResultModeType(currentResultModeType); setSelectedResultUrl(null); setPendingGeneration({ + chatId, modeType: currentResultModeType, expectedCount: currentResultModeType === "scene_generation" @@ -1919,6 +2012,7 @@ export function AgentGenerationWorkspaceDarkV2({ ? detailReplacementReferenceCards.length : skuReplacementReferenceCards.length, userTurnCountAtStart: userMessageCount, + timestamp: Date.now(), }); try { sendMessage({ role: "user", parts });