From fbdf6de3f138e44ed4389933020b5b207adb9fcf Mon Sep 17 00:00:00 2001 From: shrimbly Date: Fri, 9 Jan 2026 16:52:13 +1300 Subject: [PATCH] docs(03): update plans for separate image/video nodes - Rename target from Generate to GenerateImage - Filter model selector to image capabilities only (text-to-image, image-to-image) - Note GenerateVideo node deferred to Phase 6 --- .../03-generate-node-refactor/03-01-PLAN.md | 43 +++++++++++-------- .../03-generate-node-refactor/03-02-PLAN.md | 30 ++++++++----- .../03-generate-node-refactor/03-03-PLAN.md | 14 +++--- 3 files changed, 51 insertions(+), 36 deletions(-) diff --git a/.planning/phases/03-generate-node-refactor/03-01-PLAN.md b/.planning/phases/03-generate-node-refactor/03-01-PLAN.md index 4a923ae8..742b7971 100644 --- a/.planning/phases/03-generate-node-refactor/03-01-PLAN.md +++ b/.planning/phases/03-generate-node-refactor/03-01-PLAN.md @@ -5,10 +5,12 @@ type: execute --- -Rename NanoBanana node to Generate and add multi-provider model selector. +Rename NanoBanana node to GenerateImage and add multi-provider model selector. -Purpose: Transform the hardcoded Gemini-only node into a generic generation node that can use any provider's models. -Output: Generate node component with provider/model dropdown, updated types, store functions renamed. +Purpose: Transform the hardcoded Gemini-only node into a multi-provider image generation node that filters to image-capable models only. +Output: GenerateImage node component with provider/model dropdown (image models only), updated types, store functions renamed. + +Note: GenerateVideo node will be added in Phase 6 (Video & Polish) as a separate node type. @@ -61,18 +63,19 @@ Output: Generate node component with provider/model dropdown, updated types, sto - Task 2: Rename component to GenerateNode with model selector UI + Task 2: Rename component to GenerateImageNode with model selector UI src/components/nodes/NanoBananaNode.tsx, src/components/nodes/index.ts - 1. Rename file from NanoBananaNode.tsx to GenerateNode.tsx + 1. Rename file from NanoBananaNode.tsx to GenerateImageNode.tsx - 2. Rename component from NanoBananaNode to GenerateNode (keep function export name) + 2. Rename component from NanoBananaNode to GenerateImageNode 3. Add model selector UI that shows: - Provider dropdown (gemini, replicate, fal) - only show enabled providers - Model dropdown (fetched from /api/models for selected provider) + - **Filter to image capabilities only**: text-to-image, image-to-image - For Gemini, show existing hardcoded models (Nano Banana, Nano Banana Pro) - - For other providers, fetch models dynamically + - For other providers, fetch models dynamically with capability filter 4. When provider/model changes: - Update node data with selectedModel: { provider, modelId, displayName } @@ -81,16 +84,16 @@ Output: Generate node component with provider/model dropdown, updated types, sto 5. Keep existing aspect ratio/resolution controls for Gemini models - Hide them for non-Gemini models (parameters will come from provider schema later) - 6. Update index.ts to export GenerateNode and alias it as NanoBananaNode for backward compatibility: + 6. Update index.ts to export GenerateImageNode and alias as NanoBananaNode: ```typescript - export { GenerateNode } from "./GenerateNode"; - export { GenerateNode as NanoBananaNode } from "./GenerateNode"; + export { GenerateImageNode } from "./GenerateImageNode"; + export { GenerateImageNode as NanoBananaNode } from "./GenerateImageNode"; ``` - WHY: The component rename reflects its new multi-provider purpose. The alias maintains backward compatibility with existing imports. + WHY: The component rename reflects its image-specific purpose. Video generation will be a separate GenerateVideoNode in Phase 6. The alias maintains backward compatibility. npm run build succeeds, component renders in browser - GenerateNode.tsx exists, shows provider selector, model dropdown fetches from API for non-Gemini providers + GenerateImageNode.tsx exists, shows provider selector, model dropdown shows only image-capable models @@ -98,18 +101,18 @@ Output: Generate node component with provider/model dropdown, updated types, sto src/store/workflowStore.ts, src/components/WorkflowCanvas.tsx 1. In workflowStore.ts: - - Rename saveNanoBananaDefaults to saveGenerateDefaults (keep old name as alias) - - Rename loadNanoBananaDefaults to loadGenerateDefaults (keep old name as alias) + - Rename saveNanoBananaDefaults to saveGenerateImageDefaults (keep old name as alias) + - Rename loadNanoBananaDefaults to loadGenerateImageDefaults (keep old name as alias) - Update localStorage key comment but keep actual key for migration - Update createDefaultNodeData for "nanoBanana" case to include default selectedModel for Gemini 2. In WorkflowCanvas.tsx: - - Update nodeTypes registration to use GenerateNode - - Keep "nanoBanana" as the type key (internal type name unchanged) + - Update nodeTypes registration to use GenerateImageNode + - Keep "nanoBanana" as the type key (internal type name unchanged for now) - Update minimap color mapping if it references "nanoBanana" 3. In any file using NanoBananaNode import: - - Update import to use GenerateNode + - Update import to use GenerateImageNode - Files: ConnectionDropMenu.tsx, FloatingActionBar.tsx, etc. WHY: Internal references update to new names while keeping the node type string "nanoBanana" for workflow file compatibility. @@ -124,7 +127,8 @@ Output: Generate node component with provider/model dropdown, updated types, sto Before declaring plan complete: - [ ] `npm run build` succeeds without errors - [ ] `npx tsc --noEmit` passes type checking -- [ ] GenerateNode renders with provider dropdown +- [ ] GenerateImageNode renders with provider dropdown +- [ ] Model selector shows only image-capable models (text-to-image, image-to-image) - [ ] Gemini models show in model selector - [ ] Existing workflows with nanoBanana nodes still load @@ -133,7 +137,8 @@ Before declaring plan complete: - All tasks completed - All verification checks pass -- GenerateNode component exists with multi-provider UI +- GenerateImageNode component exists with multi-provider UI +- Model selector filters to image capabilities only - Types support both legacy Gemini and new multi-provider selection - Backward compatibility maintained for existing workflows diff --git a/.planning/phases/03-generate-node-refactor/03-02-PLAN.md b/.planning/phases/03-generate-node-refactor/03-02-PLAN.md index 4954f2c1..78957209 100644 --- a/.planning/phases/03-generate-node-refactor/03-02-PLAN.md +++ b/.planning/phases/03-generate-node-refactor/03-02-PLAN.md @@ -5,10 +5,12 @@ type: execute --- -Add provider-specific execution logic to the generate API route. +Add provider-specific execution logic to the generate API route for image generation. -Purpose: Enable the generate endpoint to route requests to the correct provider (Gemini, Replicate, fal.ai) based on the selected model. -Output: Updated /api/generate route that dispatches to provider-specific generation logic. +Purpose: Enable the generate endpoint to route requests to the correct provider (Gemini, Replicate, fal.ai) based on the selected model, filtering to image outputs only. +Output: Updated /api/generate route that dispatches to provider-specific image generation logic. + +Note: Video generation will use a separate endpoint in Phase 6. @@ -59,12 +61,16 @@ Output: Updated /api/generate route that dispatches to provider-specific generat 3. Fetch output: - Poll GET /predictions/{id} until status is "succeeded" or "failed" - Convert output URL to base64 data URL - - Return in GenerationOutput format + - Return in GenerationOutput format with type: "image" + + 4. Filter to image models only: + - Only accept models with text-to-image or image-to-image capabilities + - Return error if video model passed (video generation is Phase 6) - WHY: Replicate requires polling for async predictions. The generate() method encapsulates this complexity. + WHY: Replicate requires polling for async predictions. The generate() method encapsulates this complexity. Image-only filter keeps this endpoint focused. TypeScript compiles, generate() method exists and doesn't throw immediately - Replicate provider has working generate() method that calls prediction API + Replicate provider has working generate() method that calls prediction API for image models @@ -82,14 +88,18 @@ Output: Updated /api/generate route that dispatches to provider-specific generat - API key optional but rate limited without it 3. Parse response: - - Extract image/video URL from response + - Extract image URL from response - Convert to base64 data URL for consistency - - Handle different output formats (images array, video URL, etc.) + - Handle images array output format + + 4. Filter to image models only: + - Only accept models with text-to-image or image-to-image capabilities + - Return error if video model passed (video generation is Phase 6) - WHY: fal.ai's synchronous API is simpler than Replicate. The generate() method normalizes the response format. + WHY: fal.ai's synchronous API is simpler than Replicate. The generate() method normalizes the response format. Image-only filter keeps this endpoint focused. TypeScript compiles, generate() method exists - fal.ai provider has working generate() method that calls fal.run endpoint + fal.ai provider has working generate() method that calls fal.run endpoint for image models diff --git a/.planning/phases/03-generate-node-refactor/03-03-PLAN.md b/.planning/phases/03-generate-node-refactor/03-03-PLAN.md index da0d89ad..c19b682a 100644 --- a/.planning/phases/03-generate-node-refactor/03-03-PLAN.md +++ b/.planning/phases/03-generate-node-refactor/03-03-PLAN.md @@ -28,7 +28,7 @@ Output: Migration logic, verified backward compatibility, updated workflow execu # Key source files: @src/store/workflowStore.ts @src/types/index.ts -@src/components/nodes/GenerateNode.tsx +@src/components/nodes/GenerateImageNode.tsx **Tech stack available:** Zustand, workflow JSON persistence **Established patterns:** Workflow load/save in workflowStore @@ -97,8 +97,8 @@ Output: Migration logic, verified backward compatibility, updated workflow execu 3. Handle response format: - Provider generate() returns GenerationOutput with outputs array - - Extract first image/video output as outputImage - - For video outputs, store separately (Phase 6 handles video display) + - Extract first image output as outputImage + - Validate output type is "image" (video handled by separate node in Phase 6) WHY: The store's execution logic needs to pass provider API keys (stored client-side) to the server route. @@ -107,8 +107,8 @@ Output: Migration logic, verified backward compatibility, updated workflow execu - Task 3: Update GenerateNode to handle legacy data - src/components/nodes/GenerateNode.tsx + Task 3: Update GenerateImageNode to handle legacy data + src/components/nodes/GenerateImageNode.tsx 1. When component mounts or data changes: - If model exists but not selectedModel, derive selectedModel from model @@ -119,13 +119,13 @@ Output: Migration logic, verified backward compatibility, updated workflow execu - Model dropdown shows correct Gemini model name 3. When saving defaults, save in both formats: - - saveGenerateDefaults should save both model and selectedModel + - saveGenerateImageDefaults should save both model and selectedModel - Ensures new nodes get correct defaults WHY: The UI must correctly display legacy nodes that were migrated on load. Open workflow with old nanoBanana node, verify dropdowns show correct selection - GenerateNode displays correct provider/model for both legacy and new nodes + GenerateImageNode displays correct provider/model for both legacy and new nodes