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.
 
 

387 lines
11 KiB

/**
* Node Types
*
* Types for workflow nodes including all node data interfaces,
* handle types, and workflow node definitions.
*/
import { Node } from "@xyflow/react";
import type {
AnnotationNodeData,
AnnotationShape,
BaseNodeData,
} from "./annotation";
// Re-export types from annotation for convenience
export type { AnnotationNodeData, BaseNodeData };
// Import from domain files to avoid circular dependencies
import type { AspectRatio, Resolution, ModelType } from "./models";
import type { LLMProvider, LLMModelType, SelectedModel, ProviderType } from "./providers";
/**
* All available node types in the workflow editor
*/
export type NodeType =
| "imageInput"
| "audioInput"
| "annotation"
| "prompt"
| "promptConstructor"
| "nanoBanana"
| "generateVideo"
| "llmGenerate"
| "splitGrid"
| "output"
| "outputGallery"
| "imageCompare"
| "videoStitch"
| "easeCurve"
| "generate3d"
| "glbViewer";
/**
* Node execution status
*/
export type NodeStatus = "idle" | "loading" | "complete" | "error";
/**
* Image input node - loads/uploads images into the workflow
*/
export interface ImageInputNodeData extends BaseNodeData {
image: string | null;
imageRef?: string; // External image reference for storage optimization
filename: string | null;
dimensions: { width: number; height: number } | null;
}
/**
* Audio input node - loads/uploads audio files into the workflow
*/
export interface AudioInputNodeData extends BaseNodeData {
audioFile: string | null; // Base64 data URL of the audio file
filename: string | null; // Original filename for display
duration: number | null; // Duration in seconds
format: string | null; // MIME type (audio/mp3, audio/wav, etc.)
}
/**
* Prompt node - text input for AI generation
*/
export interface PromptNodeData extends BaseNodeData {
prompt: string;
variableName?: string; // Optional variable name for use in PromptConstructor templates
}
/**
* Prompt Constructor node - template-based prompt builder with @variable interpolation
*/
export interface PromptConstructorNodeData extends BaseNodeData {
template: string;
outputText: string | null;
unresolvedVars: string[];
}
/**
* Available variable from connected Prompt nodes (for PromptConstructor autocomplete)
*/
export interface AvailableVariable {
name: string;
value: string;
nodeId: string;
}
/**
* Image history item for tracking generated images
*/
export interface ImageHistoryItem {
id: string;
image: string; // Base64 data URL
timestamp: number; // For display & sorting
prompt: string; // The prompt used
aspectRatio: AspectRatio;
model: ModelType;
}
/**
* Carousel image item for per-node history (IDs only, images stored externally)
*/
export interface CarouselImageItem {
id: string;
timestamp: number;
prompt: string;
aspectRatio: AspectRatio;
model: ModelType;
}
/**
* Carousel video item for per-node video history
*/
export interface CarouselVideoItem {
id: string;
timestamp: number;
prompt: string;
model: string; // Model ID for video (not ModelType since external providers)
}
/**
* Model input definition for dynamic handles
*/
export interface ModelInputDef {
name: string;
type: "image" | "text";
required: boolean;
label: string;
description?: string;
}
/**
* Nano Banana node - AI image generation
*/
export interface NanoBananaNodeData extends BaseNodeData {
inputImages: string[]; // Now supports multiple images
inputImageRefs?: string[]; // External image references for storage optimization
inputPrompt: string | null;
outputImage: string | null;
outputImageRef?: string; // External image reference for storage optimization
aspectRatio: AspectRatio;
resolution: Resolution; // Only used by Nano Banana Pro
model: ModelType;
selectedModel?: SelectedModel; // Multi-provider model selection (optional for backward compat)
useGoogleSearch: boolean; // Only available for Nano Banana Pro
parameters?: Record<string, unknown>; // Model-specific parameters for external providers
inputSchema?: ModelInputDef[]; // Model's input schema for dynamic handles
status: NodeStatus;
error: string | null;
imageHistory: CarouselImageItem[]; // Carousel history (IDs only)
selectedHistoryIndex: number; // Currently selected image in carousel
}
/**
* Generate Video node - AI video generation
*/
export interface GenerateVideoNodeData extends BaseNodeData {
inputImages: string[];
inputImageRefs?: string[]; // External image references for storage optimization
inputPrompt: string | null;
outputVideo: string | null; // Video data URL or URL
outputVideoRef?: string; // External video reference for storage optimization
selectedModel?: SelectedModel; // Required for video generation (no legacy fallback)
parameters?: Record<string, unknown>; // Model-specific parameters
inputSchema?: ModelInputDef[]; // Model's input schema for dynamic handles
status: NodeStatus;
error: string | null;
videoHistory: CarouselVideoItem[]; // Carousel history (IDs only)
selectedVideoHistoryIndex: number; // Currently selected video in carousel
}
/**
* Generate 3D node - AI 3D model generation
*/
export interface Generate3DNodeData extends BaseNodeData {
inputImages: string[];
inputImageRefs?: string[];
inputPrompt: string | null;
output3dUrl: string | null;
savedFilename: string | null;
savedFilePath: string | null;
selectedModel?: SelectedModel;
parameters?: Record<string, unknown>;
inputSchema?: ModelInputDef[];
status: NodeStatus;
error: string | null;
}
/**
* LLM Generate node - AI text generation
*/
export interface LLMGenerateNodeData extends BaseNodeData {
inputPrompt: string | null;
inputImages: string[];
inputImageRefs?: string[]; // External image references for storage optimization
outputText: string | null;
provider: LLMProvider;
model: LLMModelType;
temperature: number;
maxTokens: number;
status: NodeStatus;
error: string | null;
}
/**
* Output node - displays final workflow results
*/
export interface OutputNodeData extends BaseNodeData {
image: string | null;
imageRef?: string; // External image reference for storage optimization
video?: string | null; // Video data URL or HTTP URL
contentType?: "image" | "video"; // Explicit content type hint
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
}
/**
* Image Compare node - side-by-side image comparison with draggable slider
*/
export interface ImageCompareNodeData extends BaseNodeData {
imageA: string | null;
imageB: string | null;
}
/**
* Video stitch clip - represents a single video clip in the filmstrip
*/
export interface VideoStitchClip {
edgeId: string; // Edge ID for disconnect capability
sourceNodeId: string; // Source node producing this video
thumbnail: string | null; // Base64 JPEG thumbnail
duration: number | null; // Clip duration in seconds
handleId: string; // Which input handle (video-0, video-1, etc.)
}
/**
* Video Stitch node - concatenates multiple videos into a single output
*/
export interface VideoStitchNodeData extends BaseNodeData {
clips: VideoStitchClip[]; // Ordered clip sequence for filmstrip
clipOrder: string[]; // Edge IDs in user-defined order (drag reorder)
outputVideo: string | null; // Stitched video blob URL or data URL
loopCount: 1 | 2 | 3; // How many times to repeat the clip sequence (1 = no loop)
status: NodeStatus;
error: string | null;
progress: number; // 0-100 processing progress
encoderSupported: boolean | null; // null = not checked yet, true/false after check
}
/**
* Ease Curve node - applies speed curve to video using easing functions
*/
export interface EaseCurveNodeData extends BaseNodeData {
bezierHandles: [number, number, number, number];
easingPreset: string | null;
inheritedFrom: string | null;
outputDuration: number;
outputVideo: string | null;
status: NodeStatus;
error: string | null;
progress: number;
encoderSupported: boolean | null;
}
/**
* Split Grid node - splits image into grid cells for parallel processing
*/
export interface SplitGridNodeData extends BaseNodeData {
sourceImage: string | null;
sourceImageRef?: string; // External image reference for storage optimization
targetCount: number; // 4, 6, 8, 9, or 10
defaultPrompt: string;
generateSettings: {
aspectRatio: AspectRatio;
resolution: Resolution;
model: ModelType;
useGoogleSearch: boolean;
};
childNodeIds: Array<{
imageInput: string;
prompt: string;
nanoBanana: string;
}>;
gridRows: number;
gridCols: number;
isConfigured: boolean;
status: NodeStatus;
error: string | null;
}
/**
* GLB 3D Viewer node - loads and displays 3D models, captures viewport as image
*/
export interface GLBViewerNodeData extends BaseNodeData {
glbUrl: string | null; // Object URL for the loaded GLB file
filename: string | null; // Original filename for display
capturedImage: string | null; // Base64 PNG snapshot of the 3D viewport
}
/**
* Union of all node data types
*/
export type WorkflowNodeData =
| ImageInputNodeData
| AudioInputNodeData
| AnnotationNodeData
| PromptNodeData
| PromptConstructorNodeData
| NanoBananaNodeData
| GenerateVideoNodeData
| Generate3DNodeData
| LLMGenerateNodeData
| SplitGridNodeData
| OutputNodeData
| OutputGalleryNodeData
| ImageCompareNodeData
| VideoStitchNodeData
| EaseCurveNodeData
| GLBViewerNodeData;
/**
* Workflow node with typed data (extended with optional groupId)
*/
export type WorkflowNode = Node<WorkflowNodeData, NodeType> & {
groupId?: string;
};
/**
* Handle types for node connections
*/
export type HandleType = "image" | "text" | "audio" | "video" | "3d" | "easeCurve";
/**
* Default settings for node types - stored in localStorage
*/
export interface GenerateImageNodeDefaults {
selectedModel?: {
provider: ProviderType;
modelId: string;
displayName: string;
};
aspectRatio?: string;
resolution?: string;
useGoogleSearch?: boolean;
}
export interface GenerateVideoNodeDefaults {
selectedModel?: {
provider: ProviderType;
modelId: string;
displayName: string;
};
}
export interface Generate3DNodeDefaults {
selectedModel?: {
provider: ProviderType;
modelId: string;
displayName: string;
};
}
export interface LLMNodeDefaults {
provider?: LLMProvider;
model?: LLMModelType;
temperature?: number;
maxTokens?: number;
}
export interface NodeDefaultsConfig {
generateImage?: GenerateImageNodeDefaults;
generateVideo?: GenerateVideoNodeDefaults;
generate3d?: Generate3DNodeDefaults;
llm?: LLMNodeDefaults;
}