From 957bfcc724bd15af1fa4a0a6e12395ba698af7aa Mon Sep 17 00:00:00 2001 From: shrimbly Date: Thu, 15 Jan 2026 23:37:41 +1300 Subject: [PATCH] Fix duplicate input images for generateVideo nodes The generateVideo node type was missing from imageStorage.ts, causing input images to be saved as new files on every workflow save instead of being deduplicated via refs. Co-Authored-By: Claude Opus 4.5 --- src/utils/imageStorage.ts | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/utils/imageStorage.ts b/src/utils/imageStorage.ts index bc9eab44..63768b6b 100644 --- a/src/utils/imageStorage.ts +++ b/src/utils/imageStorage.ts @@ -177,6 +177,36 @@ async function externalizeNodeImages( break; } + case "generateVideo": { + const d = data as import("@/types").GenerateVideoNodeData; + let inputImageRefs = d.inputImageRefs ? [...d.inputImageRefs] : []; + const inputImages: string[] = []; + + // Handle input images array (save to inputs) + // Skip if corresponding inputImageRef already exists + for (let i = 0; i < d.inputImages.length; i++) { + const img = d.inputImages[i]; + const existingRef = d.inputImageRefs?.[i]; + if (existingRef && isBase64DataUrl(img)) { + inputImages.push(""); // Already has ref, just clear the base64 + } else if (isBase64DataUrl(img)) { + const ref = await saveImageAndGetId(img, workflowPath, savedImageIds, "inputs"); + inputImageRefs[i] = ref; + inputImages.push(""); // Empty placeholder + } else { + inputImages.push(img); + } + } + + // Note: outputVideo is a video URL, not saved as an image + newData = { + ...d, + inputImages: inputImages.length > 0 && inputImages.every(i => i === "") ? [] : inputImages, + inputImageRefs: inputImageRefs.length > 0 ? inputImageRefs : undefined, + }; + break; + } + case "output": { const d = data as import("@/types").OutputNodeData; // Output displays generated content, save to generations @@ -374,6 +404,27 @@ async function hydrateNodeImages( break; } + case "generateVideo": { + const d = data as import("@/types").GenerateVideoNodeData; + const inputImages = [...d.inputImages]; + + // Hydrate input images from refs + if (d.inputImageRefs && d.inputImageRefs.length > 0) { + for (let i = 0; i < d.inputImageRefs.length; i++) { + const ref = d.inputImageRefs[i]; + if (ref) { + inputImages[i] = await loadImageById(ref, workflowPath, loadedImages, "inputs"); + } + } + } + + newData = { + ...d, + inputImages, + }; + break; + } + case "output": { const d = data as import("@/types").OutputNodeData; if (d.imageRef && !d.image) {