fix: preserve workflow prompt state in agent mode
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-03-24 01:45:20 +08:00
parent 328f1f4915
commit 14b6b3ec10
2 changed files with 106 additions and 18 deletions

View File

@ -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 = {

View File

@ -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<Set<string>>(new Set());
const previousBrandForModelRef = useRef("");
const autoSelectedBrandModelBrandRef = useRef("");
const lastLoadedCanvasIdRef = useRef<string>("");
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) => {