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.
364 lines
9.7 KiB
364 lines
9.7 KiB
import { Node, Edge } from "@xyflow/react";
|
|
|
|
// Node Types
|
|
export type NodeType =
|
|
| "imageInput"
|
|
| "annotation"
|
|
| "prompt"
|
|
| "nanoBanana"
|
|
| "generateVideo"
|
|
| "llmGenerate"
|
|
| "splitGrid"
|
|
| "output";
|
|
|
|
// Aspect Ratios (supported by both Nano Banana and Nano Banana Pro)
|
|
export type AspectRatio = "1:1" | "2:3" | "3:2" | "3:4" | "4:3" | "4:5" | "5:4" | "9:16" | "16:9" | "21:9";
|
|
|
|
// Resolution Options (only supported by Nano Banana Pro)
|
|
export type Resolution = "1K" | "2K" | "4K";
|
|
|
|
// Image Generation Model Options
|
|
export type ModelType = "nano-banana" | "nano-banana-pro";
|
|
|
|
// LLM Provider Options
|
|
export type LLMProvider = "google" | "openai";
|
|
|
|
// LLM Model Options
|
|
export type LLMModelType =
|
|
| "gemini-2.5-flash"
|
|
| "gemini-3-flash-preview"
|
|
| "gemini-3-pro-preview"
|
|
| "gpt-4.1-mini"
|
|
| "gpt-4.1-nano";
|
|
|
|
// Node Status
|
|
export type NodeStatus = "idle" | "loading" | "complete" | "error";
|
|
|
|
// Base node data - using Record to satisfy React Flow's type constraints
|
|
export interface BaseNodeData extends Record<string, unknown> {
|
|
label?: string;
|
|
customTitle?: string;
|
|
comment?: string;
|
|
}
|
|
|
|
// Image Input Node Data
|
|
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;
|
|
}
|
|
|
|
// Annotation Shape Types
|
|
export type ShapeType = "rectangle" | "circle" | "arrow" | "freehand" | "text";
|
|
|
|
export interface BaseShape {
|
|
id: string;
|
|
type: ShapeType;
|
|
x: number;
|
|
y: number;
|
|
stroke: string;
|
|
strokeWidth: number;
|
|
opacity: number;
|
|
}
|
|
|
|
export interface RectangleShape extends BaseShape {
|
|
type: "rectangle";
|
|
width: number;
|
|
height: number;
|
|
fill: string | null;
|
|
}
|
|
|
|
export interface CircleShape extends BaseShape {
|
|
type: "circle";
|
|
radiusX: number;
|
|
radiusY: number;
|
|
fill: string | null;
|
|
}
|
|
|
|
export interface ArrowShape extends BaseShape {
|
|
type: "arrow";
|
|
points: number[];
|
|
}
|
|
|
|
export interface FreehandShape extends BaseShape {
|
|
type: "freehand";
|
|
points: number[];
|
|
}
|
|
|
|
export interface TextShape extends BaseShape {
|
|
type: "text";
|
|
text: string;
|
|
fontSize: number;
|
|
fill: string;
|
|
}
|
|
|
|
export type AnnotationShape =
|
|
| RectangleShape
|
|
| CircleShape
|
|
| ArrowShape
|
|
| FreehandShape
|
|
| TextShape;
|
|
|
|
// Annotation Node Data
|
|
export interface AnnotationNodeData extends BaseNodeData {
|
|
sourceImage: string | null;
|
|
sourceImageRef?: string; // External image reference for storage optimization
|
|
annotations: AnnotationShape[];
|
|
outputImage: string | null;
|
|
outputImageRef?: string; // External image reference for storage optimization
|
|
}
|
|
|
|
// Prompt Node Data
|
|
export interface PromptNodeData extends BaseNodeData {
|
|
prompt: 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)
|
|
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 Data (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 Data (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
|
|
}
|
|
|
|
// LLM Generate Node Data (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 Data
|
|
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
|
|
}
|
|
|
|
// Split Grid Node Data (Utility Node)
|
|
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;
|
|
}
|
|
|
|
// Union of all node data types
|
|
export type WorkflowNodeData =
|
|
| ImageInputNodeData
|
|
| AnnotationNodeData
|
|
| PromptNodeData
|
|
| NanoBananaNodeData
|
|
| GenerateVideoNodeData
|
|
| LLMGenerateNodeData
|
|
| SplitGridNodeData
|
|
| OutputNodeData;
|
|
|
|
// Workflow Node with typed data (extended with optional groupId)
|
|
export type WorkflowNode = Node<WorkflowNodeData, NodeType> & {
|
|
groupId?: string;
|
|
};
|
|
|
|
// Workflow Edge Data
|
|
export interface WorkflowEdgeData extends Record<string, unknown> {
|
|
hasPause?: boolean;
|
|
}
|
|
|
|
// Workflow Edge
|
|
export type WorkflowEdge = Edge<WorkflowEdgeData>;
|
|
|
|
// Handle Types for connections
|
|
export type HandleType = "image" | "text";
|
|
|
|
// API Request/Response types for Image Generation
|
|
export interface GenerateRequest {
|
|
images: string[]; // Now supports multiple images
|
|
prompt: string;
|
|
aspectRatio?: AspectRatio;
|
|
resolution?: Resolution; // Only for Nano Banana Pro
|
|
model?: ModelType;
|
|
useGoogleSearch?: boolean; // Only for Nano Banana Pro
|
|
}
|
|
|
|
export interface GenerateResponse {
|
|
success: boolean;
|
|
image?: string;
|
|
video?: string;
|
|
videoUrl?: string; // For large videos, return URL directly
|
|
contentType?: "image" | "video";
|
|
error?: string;
|
|
}
|
|
|
|
// API Request/Response types for LLM Text Generation
|
|
export interface LLMGenerateRequest {
|
|
prompt: string;
|
|
images?: string[];
|
|
provider: LLMProvider;
|
|
model: LLMModelType;
|
|
temperature?: number;
|
|
maxTokens?: number;
|
|
}
|
|
|
|
export interface LLMGenerateResponse {
|
|
success: boolean;
|
|
text?: string;
|
|
error?: string;
|
|
}
|
|
|
|
// Tool Types for annotation
|
|
export type ToolType = "select" | "rectangle" | "circle" | "arrow" | "freehand" | "text";
|
|
|
|
// Tool Options
|
|
export interface ToolOptions {
|
|
strokeColor: string;
|
|
strokeWidth: number;
|
|
fillColor: string | null;
|
|
fontSize: number;
|
|
opacity: number;
|
|
}
|
|
|
|
// Auto-save configuration stored in localStorage
|
|
export interface WorkflowSaveConfig {
|
|
workflowId: string;
|
|
name: string;
|
|
directoryPath: string;
|
|
generationsPath: string | null;
|
|
lastSavedAt: number | null;
|
|
}
|
|
|
|
// Cost tracking data stored per-workflow in localStorage
|
|
export interface WorkflowCostData {
|
|
workflowId: string;
|
|
incurredCost: number;
|
|
lastUpdated: number;
|
|
}
|
|
|
|
// Group background color options (dark mode tints)
|
|
export type GroupColor =
|
|
| "neutral"
|
|
| "blue"
|
|
| "green"
|
|
| "purple"
|
|
| "orange"
|
|
| "red";
|
|
|
|
// Group definition stored in workflow
|
|
export interface NodeGroup {
|
|
id: string;
|
|
name: string;
|
|
color: GroupColor;
|
|
position: { x: number; y: number };
|
|
size: { width: number; height: number };
|
|
locked?: boolean;
|
|
}
|
|
|
|
// Provider Types for multi-provider support
|
|
export type ProviderType = "gemini" | "openai" | "replicate" | "fal";
|
|
|
|
// Selected model for image/video generation nodes
|
|
export interface SelectedModel {
|
|
provider: ProviderType;
|
|
modelId: string;
|
|
displayName: string;
|
|
}
|
|
|
|
export interface ProviderConfig {
|
|
id: ProviderType;
|
|
name: string;
|
|
enabled: boolean;
|
|
apiKey: string | null;
|
|
apiKeyEnvVar?: string; // For providers using environment variables (e.g., Gemini)
|
|
}
|
|
|
|
export interface ProviderSettings {
|
|
providers: Record<ProviderType, ProviderConfig>;
|
|
}
|
|
|