diff --git a/.planning/STATE.md b/.planning/STATE.md index 0041879a..0f92ef8c 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -9,19 +9,19 @@ See: .planning/PROJECT.md (updated 2026-01-09) ## Current Position -Phase: 35 of 35 (Large Workflow Handling) -Plan: 3 of 3 in current phase -Status: Complete -Last activity: 2026-01-31 - Completed plan 03 (Client-side wiring and selection chip) +Phase: 40 of 40 (Node Enhancements) +Plan: 2 of 4 in current phase +Status: In Progress +Last activity: 2026-02-01 - Completed 40-02-PLAN.md (Connection numbering) -Progress: ██████████ 100% +Progress: ███████████░ 94% ## Performance Metrics **Velocity:** -- Total plans completed: 37 -- Average duration: 6.9 min -- Total execution time: 4.25 hours +- Total plans completed: 38 +- Average duration: 6.7 min +- Total execution time: 4.28 hours **By Phase:** @@ -57,10 +57,11 @@ Progress: ██████████ 100% | 33. Workflow Edit Safety | 2/2 | 5 min | 5 min | | 34. Agentic Workflow Editing | 3/3 | 13 min | 4.3 min | | 35. Large Workflow Handling | 3/3 | 18 min | 6 min | +| 40. Node Enhancements | 2/4 | 2 min | 2 min | **Recent Trend:** -- Last 5 plans: 8 min, <1 min, 10 min, 3 min, 10 min, 5 min -- Trend: Phase 35 complete - large workflow handling with selection-aware chat context (TDD + execution) +- Last 5 plans: <1 min, 10 min, 3 min, 10 min, 5 min, 2 min +- Trend: Phase 40 in progress - node enhancements (connection numbering complete) ## Accumulated Context @@ -180,6 +181,9 @@ Recent decisions affecting current work: - Ref fields (imageRef, outputImageRef, etc.) completely removed from LLM context - All node parameters, positions, and model settings preserved in stripped context - Enhanced WorkflowContext includes full StrippedNode[] with all non-binary data +- createdAt timestamp on edge data for stable connection ordering +- Image edge sequence numbers shown only when 2+ connections to same target +- EdgeToolbar displays "Image N" labels for multi-image connections ### Deferred Issues @@ -215,7 +219,7 @@ Recent decisions affecting current work: ## Session Continuity -Last session: 2026-01-31 -Stopped at: Completed Phase 35 Plan 03 (Client-side wiring and selection chip) - Phase 35 COMPLETE +Last session: 2026-02-01 +Stopped at: Completed 40-02-PLAN.md (Connection numbering) Resume file: None -Next action: Phase 35 completes Milestone v1.4 (Agentic Workflow Builder). Ready for Milestone v1.5 (Store Refactoring) or new priorities. +Next action: Continue Phase 40 - 2 more plans remaining (OutputGallery, ImageCompare, PromptConstructor) diff --git a/src/components/ConnectionDropMenu.tsx b/src/components/ConnectionDropMenu.tsx index 7f460ef5..9f4ff10f 100644 --- a/src/components/ConnectionDropMenu.tsx +++ b/src/components/ConnectionDropMenu.tsx @@ -70,6 +70,15 @@ const IMAGE_TARGET_OPTIONS: MenuOption[] = [ ), }, + { + type: "outputGallery", + label: "Output Gallery", + icon: ( + + + + ), + }, ]; const TEXT_TARGET_OPTIONS: MenuOption[] = [ diff --git a/src/components/WorkflowCanvas.tsx b/src/components/WorkflowCanvas.tsx index c313268e..557ef427 100644 --- a/src/components/WorkflowCanvas.tsx +++ b/src/components/WorkflowCanvas.tsx @@ -28,6 +28,7 @@ import { LLMGenerateNode, SplitGridNode, OutputNode, + OutputGalleryNode, } from "./nodes"; import { EditableEdge, ReferenceEdge } from "./edges"; import { ConnectionDropMenu, MenuAction } from "./ConnectionDropMenu"; @@ -52,6 +53,7 @@ const nodeTypes: NodeTypes = { llmGenerate: LLMGenerateNode, splitGrid: SplitGridNode, output: OutputNode, + outputGallery: OutputGalleryNode, }; const edgeTypes: EdgeTypes = { @@ -96,6 +98,8 @@ const getNodeHandles = (nodeType: string): { inputs: string[]; outputs: string[] return { inputs: ["image"], outputs: ["reference"] }; case "output": return { inputs: ["image"], outputs: [] }; + case "outputGallery": + return { inputs: ["image"], outputs: [] }; default: return { inputs: [], outputs: [] }; } @@ -887,6 +891,7 @@ export function WorkflowCanvas() { llmGenerate: { width: 320, height: 360 }, splitGrid: { width: 300, height: 320 }, output: { width: 320, height: 320 }, + outputGallery: { width: 320, height: 360 }, }; const dims = defaultDimensions[nodeType]; addNode(nodeType, { x: centerX - dims.width / 2, y: centerY - dims.height / 2 }); @@ -1374,6 +1379,8 @@ export function WorkflowCanvas() { return "#f59e0b"; case "output": return "#ef4444"; + case "outputGallery": + return "#ec4899"; default: return "#94a3b8"; } diff --git a/src/components/nodes/index.ts b/src/components/nodes/index.ts index acb08ccf..21988113 100644 --- a/src/components/nodes/index.ts +++ b/src/components/nodes/index.ts @@ -6,4 +6,5 @@ export { GenerateVideoNode } from "./GenerateVideoNode"; export { LLMGenerateNode } from "./LLMGenerateNode"; export { SplitGridNode } from "./SplitGridNode"; export { OutputNode } from "./OutputNode"; +export { OutputGalleryNode } from "./OutputGalleryNode"; export { GroupNode } from "./GroupNode"; diff --git a/src/store/utils/nodeDefaults.ts b/src/store/utils/nodeDefaults.ts index 05c19b76..9443c17b 100644 --- a/src/store/utils/nodeDefaults.ts +++ b/src/store/utils/nodeDefaults.ts @@ -8,6 +8,7 @@ import { LLMGenerateNodeData, SplitGridNodeData, OutputNodeData, + OutputGalleryNodeData, WorkflowNodeData, GroupColor, SelectedModel, @@ -27,6 +28,7 @@ export const defaultNodeDimensions: Record { image: null, outputFilename: "", } as OutputNodeData; + case "outputGallery": + return { + images: [], + } as OutputGalleryNodeData; } }; diff --git a/src/store/workflowStore.ts b/src/store/workflowStore.ts index 81c72c8f..37d2fc62 100644 --- a/src/store/workflowStore.ts +++ b/src/store/workflowStore.ts @@ -1774,6 +1774,12 @@ export const useWorkflowStore = create((set, get) => ({ } break; } + + case "outputGallery": { + const { images } = getConnectedInputs(node.id); + updateNodeData(node.id, { images }); + break; + } } } diff --git a/src/types/nodes.ts b/src/types/nodes.ts index 8bb23dd1..d167d161 100644 --- a/src/types/nodes.ts +++ b/src/types/nodes.ts @@ -30,7 +30,8 @@ export type NodeType = | "generateVideo" | "llmGenerate" | "splitGrid" - | "output"; + | "output" + | "outputGallery"; /** * Node execution status @@ -165,6 +166,13 @@ export interface OutputNodeData extends BaseNodeData { outputFilename?: string; // Custom filename for saved outputs (without extension) } +/** + * Output Gallery node - displays scrollable thumbnail grid of images with lightbox + */ +export interface OutputGalleryNodeData extends BaseNodeData { + images: string[]; // Array of base64 data URLs from connected nodes +} + /** * Split Grid node - splits image into grid cells for parallel processing */ @@ -202,7 +210,8 @@ export type WorkflowNodeData = | GenerateVideoNodeData | LLMGenerateNodeData | SplitGridNodeData - | OutputNodeData; + | OutputNodeData + | OutputGalleryNodeData; /** * Workflow node with typed data (extended with optional groupId)