From 14b6b3ec1085aaa5a827784ab3a4e8190f2a8c2a Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 24 Mar 2026 01:45:20 +0800 Subject: [PATCH] fix: preserve workflow prompt state in agent mode --- app/(chat)/api/chat/route.ts | 11 ++++ app/canvas/[id]/page.tsx | 113 +++++++++++++++++++++++++++++------ 2 files changed, 106 insertions(+), 18 deletions(-) diff --git a/app/(chat)/api/chat/route.ts b/app/(chat)/api/chat/route.ts index 2ace8ea1b..676a301fc 100644 --- a/app/(chat)/api/chat/route.ts +++ b/app/(chat)/api/chat/route.ts @@ -5637,6 +5637,17 @@ export async function POST(request: Request) { ? applyHiddenPromptToMessages(uiMessages, hiddenPromptText) : uiMessages; + if (hiddenPromptText) { + const hiddenPromptLines = hiddenPromptText + .split("\n") + .map((line) => line.trim()) + .filter(Boolean); + console.info("[Chat API] Hidden workflow prompt summary:", { + lineCount: hiddenPromptLines.length, + preview: hiddenPromptLines.slice(0, 12), + }); + } + const { longitude, latitude, city, country } = geolocation(request); const requestHints: RequestHints = { diff --git a/app/canvas/[id]/page.tsx b/app/canvas/[id]/page.tsx index 0e8fbc826..f9ce052df 100644 --- a/app/canvas/[id]/page.tsx +++ b/app/canvas/[id]/page.tsx @@ -133,6 +133,29 @@ const SIZE_PRESETS = [ { label: "9:16", value: "9:16", width: 1024, height: 1820 }, ]; +function hasMeaningfulWorkflowState( + workflowState: AgentWorkflowPersistedState | null | undefined +) { + if (!workflowState) return false; + + const inputs = workflowState.inputs; + const hasInputs = Boolean( + String(inputs?.primarySku || "").trim() || + String(inputs?.secondarySku || "").trim() || + String(inputs?.brand || "").trim() || + String(inputs?.store || "").trim() || + String(inputs?.priceBand || "").trim() + ); + + const hasSelections = Object.values(workflowState.selections || {}).some((value) => + Boolean(String(value || "").trim()) + ); + const hasBrandModel = Boolean(String(workflowState.selectedBrandModel?.imageUrl || "").trim()); + const hasPreset = Boolean(String(workflowState.selectedAgentPresetId || "").trim()); + + return hasInputs || hasSelections || hasBrandModel || hasPreset; +} + const FLOATING_PANEL_WIDTH = 460; const FLOATING_PANEL_INSET = 16; const DOCKED_PANEL_INSET = 0; @@ -306,6 +329,7 @@ export default function CanvasEditorPage({ params }: PageProps) { const previousNodeIdsRef = useRef>(new Set()); const previousBrandForModelRef = useRef(""); const autoSelectedBrandModelBrandRef = useRef(""); + const lastLoadedCanvasIdRef = useRef(""); const requestedAgentMode = mode === "agent"; const isAgentWorkspaceEnabled = siteSettingsData?.agentEnabled !== false; const isCanvasAgentModeEnabled = siteSettingsData?.canvasAgentModeEnabled !== false; @@ -364,24 +388,58 @@ export default function CanvasEditorPage({ params }: PageProps) { setPanelMode("chat"); }, [agentProjectId, isAgentMode, updateCanvasSearchParams]); + const buildCurrentWorkflowPersistedState = useCallback((): AgentWorkflowPersistedState => { + return { + inputs: { + primarySku: workflowInputs.primarySku.trim(), + secondarySku: workflowInputs.secondarySku.trim(), + brand: workflowInputs.brand.trim(), + store: workflowInputs.store.trim(), + priceBand: workflowInputs.priceBand.trim(), + }, + materials: workflowMaterials, + selections: workflowSelections, + selectedBrandModel, + selectedAgentPresetId: selectedAgentPresetId || null, + currentStage: currentAgentStage, + agentModeState, + }; + }, [ + agentModeState, + currentAgentStage, + selectedAgentPresetId, + selectedBrandModel, + workflowInputs, + workflowMaterials, + workflowSelections, + ]); + // 加载画布数据 useLayoutEffect(() => { console.log('[Canvas] Loading project:', id); const loadProject = async () => { + const preservedWorkflowState = buildCurrentWorkflowPersistedState(); + const shouldPreserveCurrentWorkflowState = + requestedAgentMode && + lastLoadedCanvasIdRef.current === id && + hasMeaningfulWorkflowState(preservedWorkflowState); + setIsLoading(true); setWorkflowHydrationSource("pending"); - setWorkflowInputs({ - primarySku: "", - secondarySku: "", - brand: "", - store: "", - priceBand: "", - }); - setWorkflowMaterials(createEmptyAgentWorkflowMaterialSelections()); - setWorkflowSelections({}); - setSelectedBrandModel(null); - setSelectedAgentPresetId(null); + if (!shouldPreserveCurrentWorkflowState) { + setWorkflowInputs({ + primarySku: "", + secondarySku: "", + brand: "", + store: "", + priceBand: "", + }); + setWorkflowMaterials(createEmptyAgentWorkflowMaterialSelections()); + setWorkflowSelections({}); + setSelectedBrandModel(null); + setSelectedAgentPresetId(null); + } setAgentModeState(createEmptyAgentModeWorkspaceState()); setAgentWorkspaceState(createEmptyAgentGenerationProjectWorkspaceState()); setAgentProjectTitle("未命名生图项目"); @@ -447,6 +505,8 @@ export default function CanvasEditorPage({ params }: PageProps) { normalizeAgentModeWorkspaceState(persistedWorkflow.agentModeState) ); setWorkflowHydrationSource("project"); + } else if (requestedAgentMode && shouldPreserveCurrentWorkflowState) { + setWorkflowHydrationSource("project"); } else { setWorkflowHydrationSource("empty"); } @@ -468,10 +528,11 @@ export default function CanvasEditorPage({ params }: PageProps) { } } setIsLoading(false); + lastLoadedCanvasIdRef.current = id; }; loadProject(); - }, [id, requestedAgentMode]); + }, [buildCurrentWorkflowPersistedState, id, requestedAgentMode]); useEffect(() => { const updateViewportWidth = () => setViewportWidth(window.innerWidth); @@ -663,7 +724,7 @@ export default function CanvasEditorPage({ params }: PageProps) { try { const result = await agentProjectService.createProject({ title: buildDefaultAgentProjectTitle(), - projectState: createEmptyAgentGenerationProjectPersistedState(), + projectState: buildPersistedAgentProjectState(), }); if (!result.success || !result.data) { throw new Error(result.error || "创建生图项目失败"); @@ -688,7 +749,13 @@ export default function CanvasEditorPage({ params }: PageProps) { return () => { cancelled = true; }; - }, [agentProjectId, isAgentWorkspaceEnabled, requestedAgentMode, updateCanvasSearchParams]); + }, [ + agentProjectId, + buildPersistedAgentProjectState, + isAgentWorkspaceEnabled, + requestedAgentMode, + updateCanvasSearchParams, + ]); useEffect(() => { if (!requestedAgentMode || !agentProjectId) return; @@ -706,7 +773,12 @@ export default function CanvasEditorPage({ params }: PageProps) { const persistedState = normalizeAgentGenerationProjectPersistedState( result.data.projectState ); - const persistedWorkflow = persistedState.workflowState; + const currentWorkflowState = buildCurrentWorkflowPersistedState(); + const persistedWorkflow = hasMeaningfulWorkflowState(persistedState.workflowState) + ? persistedState.workflowState + : hasMeaningfulWorkflowState(currentWorkflowState) + ? currentWorkflowState + : persistedState.workflowState; setWorkflowInputs({ primarySku: String(persistedWorkflow.inputs?.primarySku || "").trim(), @@ -742,7 +814,7 @@ export default function CanvasEditorPage({ params }: PageProps) { return () => { cancelled = true; }; - }, [agentProjectId, requestedAgentMode]); + }, [agentProjectId, buildCurrentWorkflowPersistedState, requestedAgentMode]); useEffect(() => { if (!isAgentMode || !agentProjectId || isAgentProjectLoading) return; @@ -843,7 +915,7 @@ export default function CanvasEditorPage({ params }: PageProps) { const result = await agentProjectService.createProject({ title: buildDefaultAgentProjectTitle(), - projectState: createEmptyAgentGenerationProjectPersistedState(), + projectState: buildPersistedAgentProjectState(), }); if (!result.success || !result.data) { toast.error(result.error || "创建生图项目失败"); @@ -854,7 +926,12 @@ export default function CanvasEditorPage({ params }: PageProps) { mode: "agent", agentProjectId: result.data.id, }); - }, [agentProjectId, persistAgentProject, updateCanvasSearchParams]); + }, [ + agentProjectId, + buildPersistedAgentProjectState, + persistAgentProject, + updateCanvasSearchParams, + ]); const handleSelectAgentProject = useCallback( async (nextProjectId: string) => {