From 3e7e5d117716150da87b9bcd538691e39bfc3127 Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 24 Mar 2026 03:44:51 +0800 Subject: [PATCH] fix: migrate legacy agent results by mode --- lib/agents/generation-project-state.ts | 106 +++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 8 deletions(-) diff --git a/lib/agents/generation-project-state.ts b/lib/agents/generation-project-state.ts index ff418f0e1..3a1d79f4a 100644 --- a/lib/agents/generation-project-state.ts +++ b/lib/agents/generation-project-state.ts @@ -9,6 +9,7 @@ import { import type { AgentGenerationProjectPersistedState, AgentGenerationProjectResultCollections, + AgentGenerationResultModeType, AgentGenerationProjectWorkspaceState, AgentWorkflowPersistedState, } from "@/types/agent"; @@ -77,6 +78,95 @@ function normalizeResultCollections(value: unknown): AgentGenerationProjectResul }; } +function inferLegacyResultModeType( + workflowState: AgentWorkflowPersistedState, + resultUrls: string[] +): AgentGenerationResultModeType { + const detailReferenceCount = workflowState.agentModeState?.detailReplacement?.references?.length || 0; + const skuReferenceCount = workflowState.agentModeState?.skuReplacement?.references?.length || 0; + const resultCount = resultUrls.length; + + if (detailReferenceCount > 0 && skuReferenceCount === 0) { + return "detail_replacement"; + } + + if (skuReferenceCount > 0 && detailReferenceCount === 0) { + return "sku_replacement"; + } + + if (detailReferenceCount > 0 || skuReferenceCount > 0) { + const detailGap = Math.abs(resultCount - detailReferenceCount); + const skuGap = Math.abs(resultCount - skuReferenceCount); + return detailGap <= skuGap ? "detail_replacement" : "sku_replacement"; + } + + return "scene_generation"; +} + +function normalizeMigratedResultCollections(params: { + workflowState: AgentWorkflowPersistedState; + resultImageUrls: string[]; + resultCollections: AgentGenerationProjectResultCollections; +}) { + const normalizedSceneUrls = params.resultCollections.scene_generation || []; + const normalizedDetailUrls = params.resultCollections.detail_replacement || []; + const normalizedSkuUrls = params.resultCollections.sku_replacement || []; + const hasExplicitBuckets = + normalizedSceneUrls.length > 0 || + normalizedDetailUrls.length > 0 || + normalizedSkuUrls.length > 0; + + if (!hasExplicitBuckets && params.resultImageUrls.length > 0) { + const inferredModeType = inferLegacyResultModeType( + params.workflowState, + params.resultImageUrls + ); + return { + scene_generation: + inferredModeType === "scene_generation" ? params.resultImageUrls : [], + detail_replacement: + inferredModeType === "detail_replacement" ? params.resultImageUrls : [], + sku_replacement: + inferredModeType === "sku_replacement" ? params.resultImageUrls : [], + } satisfies AgentGenerationProjectResultCollections; + } + + const detailReferenceCount = + params.workflowState.agentModeState?.detailReplacement?.references?.length || 0; + const skuReferenceCount = + params.workflowState.agentModeState?.skuReplacement?.references?.length || 0; + + if ( + normalizedSceneUrls.length > 0 && + normalizedDetailUrls.length === 0 && + normalizedSkuUrls.length === 0 + ) { + if ( + detailReferenceCount > 0 && + normalizedSceneUrls.length >= Math.max(4, Math.floor(detailReferenceCount * 0.6)) + ) { + return { + scene_generation: [], + detail_replacement: normalizedSceneUrls, + sku_replacement: [], + } satisfies AgentGenerationProjectResultCollections; + } + + if ( + skuReferenceCount > 0 && + normalizedSceneUrls.length >= Math.max(4, Math.floor(skuReferenceCount * 0.6)) + ) { + return { + scene_generation: [], + detail_replacement: [], + sku_replacement: normalizedSceneUrls, + } satisfies AgentGenerationProjectResultCollections; + } + } + + return params.resultCollections; +} + function normalizeWorkspaceState(value: unknown): AgentGenerationProjectWorkspaceState { const raw = value && typeof value === "object" && !Array.isArray(value) @@ -178,17 +268,17 @@ export function normalizeAgentGenerationProjectPersistedState( ) ).slice(0, 64) : []; - const resultCollections = normalizeResultCollections(raw.resultCollections); + const workflowState = normalizeWorkflowState(raw.workflowState); + const resultCollections = normalizeMigratedResultCollections({ + workflowState, + resultImageUrls, + resultCollections: normalizeResultCollections(raw.resultCollections), + }); return { - workflowState: normalizeWorkflowState(raw.workflowState), + workflowState, workspaceState: normalizeWorkspaceState(raw.workspaceState), resultImageUrls, - resultCollections: { - ...resultCollections, - scene_generation: resultCollections.scene_generation?.length - ? resultCollections.scene_generation - : resultImageUrls, - }, + resultCollections, }; }