You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

7.6 KiB

phase plan type
09-video-history 1 execute
Add history carousel for generated videos in GenerateVideoNode, matching the image history pattern.

Purpose: Allow users to browse through previously generated videos without re-generating, improving workflow iteration speed. Output: GenerateVideoNode with carousel navigation controls and persistent video history stored to generations folder.

<execution_context> ~/.claude/get-shit-done/workflows/execute-phase.md ~/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md

Key reference files (pattern to follow):

@src/components/nodes/GenerateImageNode.tsx - Has carousel controls to copy pattern from (lines 295-334, 609-636) @src/types/index.ts - Has ImageHistoryItem/CarouselImageItem types (lines 117-134) @src/store/workflowStore.ts - Has imageHistory handling in executeWorkflow (lines 1201-1207, 1893-1899) @src/app/api/load-generation/route.ts - Currently only handles .png, needs video support @src/app/api/save-generation/route.ts - Already supports video (line 12-16), good reference

Files to modify:

@src/components/nodes/GenerateVideoNode.tsx

Task 1: Add video history types and store support src/types/index.ts, src/store/workflowStore.ts 1. In src/types/index.ts: - Add `CarouselVideoItem` type after `CarouselImageItem` (line ~135): ```typescript export interface CarouselVideoItem { id: string; timestamp: number; prompt: string; model: string; // Model ID for video (not ModelType since external providers) } ``` - Update `GenerateVideoNodeData` interface (line ~165) to add: ```typescript videoHistory: CarouselVideoItem[]; selectedVideoHistoryIndex: number; ```
  1. In src/store/workflowStore.ts:
    • Update createDefaultNodeData for "generateVideo" case (around line 214) to include:
      videoHistory: [],
      selectedVideoHistoryIndex: 0,
      
    • In executeWorkflow where generateVideo success is handled (around line 1392-1398), add video history tracking after setting outputVideo:
      • Generate unique ID: const videoId = crypto.randomUUID();
      • Create history item: { id: videoId, timestamp: Date.now(), prompt: text || '', model: nodeData.selectedModel?.modelId || '' }
      • Update history array (prepend new item): videoHistory: [newHistoryItem, ...(nodeData.videoHistory || [])].slice(0, 50)
      • Set selectedVideoHistoryIndex: 0
      • Call save-generation API with video and videoId (async, don't await)
    • Do the same for regenerateNode video handling (around line 2136-2142)

Import crypto from Node.js is not needed - use Math.random() fallback pattern already in codebase, or check if crypto.randomUUID exists. TypeScript compiles: npm run build passes without type errors related to video history GenerateVideoNodeData has videoHistory and selectedVideoHistoryIndex fields. Workflow execution saves videos to history and persists to generations folder.

Task 2: Update load-generation API to support video formats src/app/api/load-generation/route.ts Update the load-generation API to handle video files in addition to images:
  1. Change the hardcoded .png extension logic (line 54) to search for the file by ID with multiple extensions:

    • Define supported extensions: const extensions = ['png', 'jpg', 'jpeg', 'webp', 'gif', 'mp4', 'webm', 'mov'];
    • Loop through extensions to find the file that exists
    • If no file found with any extension, return 404
  2. Update the MIME type detection based on actual file extension found:

    const extToMime: Record<string, string> = {
      png: 'image/png',
      jpg: 'image/jpeg',
      jpeg: 'image/jpeg',
      webp: 'image/webp',
      gif: 'image/gif',
      mp4: 'video/mp4',
      webm: 'video/webm',
      mov: 'video/quicktime',
    };
    
  3. Return appropriate response field:

    • For images: { success: true, image: dataUrl }
    • For videos: { success: true, video: dataUrl }
    • Include contentType field to indicate type: contentType: extension.startsWith('mp4') || extension === 'webm' || extension === 'mov' ? 'video' : 'image' API handles video loading: Create a test .mp4 file in generations folder and verify the endpoint returns it correctly load-generation API can load both images and videos by ID, with correct MIME types and response fields
Task 3: Add carousel controls to GenerateVideoNode src/components/nodes/GenerateVideoNode.tsx Add carousel UI and navigation to GenerateVideoNode, following GenerateImageNode pattern:
  1. Add state for loading:

    const [isLoadingCarouselVideo, setIsLoadingCarouselVideo] = useState(false);
    
  2. Get generationsPath from store:

    const generationsPath = useWorkflowStore((state) => state.generationsPath);
    
  3. Add loadVideoById callback (copy pattern from GenerateImageNode lines 266-293):

    const loadVideoById = useCallback(async (videoId: string) => {
      if (!generationsPath) return null;
      try {
        const response = await fetch("/api/load-generation", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ directoryPath: generationsPath, imageId: videoId }),
        });
        if (!response.ok) return null;
        const result = await response.json();
        return result.success ? (result.video || result.image) : null;
      } catch { return null; }
    }, [generationsPath]);
    
  4. Add carousel navigation handlers (copy pattern from GenerateImageNode lines 295-333):

    const handleCarouselPrevious = useCallback(async () => { ... }, [...]);
    const handleCarouselNext = useCallback(async () => { ... }, [...]);
    

    Adapt for video: use videoHistory, selectedVideoHistoryIndex, outputVideo

  5. Add carousel UI after the video element, inside the outputVideo conditional (around line 388):

    • Check hasCarouselVideos = (nodeData.videoHistory || []).length > 1
    • Add carousel controls div with prev/next buttons (copy from GenerateImageNode lines 609-636)
    • Show "N / M" indicator using videoHistory length and selectedVideoHistoryIndex
  6. Add loading overlay for carousel navigation (copy from GenerateImageNode lines 572-595):

    • Inside the video preview div, add conditional overlay when isLoadingCarouselVideo is true Visual inspection: Generate 2+ videos with same node, verify carousel appears and navigation works GenerateVideoNode has prev/next carousel buttons showing after first regeneration, allowing users to browse video history
Before declaring phase complete: - [ ] `npm run build` succeeds without errors - [ ] GenerateVideoNode shows carousel controls after 2+ generations - [ ] Carousel navigation loads previous videos from disk - [ ] Videos persist across page refresh (stored in generations folder) - [ ] No TypeScript errors

<success_criteria>

  • All tasks completed
  • All verification checks pass
  • Video history works identically to image history pattern
  • Carousel shows N/M indicator and prev/next navigation
  • Videos saved to and loaded from generations folder </success_criteria>
After completion, create `.planning/phases/09-video-history/09-01-SUMMARY.md` following summary template.