Each slot lists the nodes it links to as chips that jump to them, and flags required inputs with nothing connected. Links to a subgraph's own input or output show as plain chips. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
375 lines
10 KiB
TypeScript
375 lines
10 KiB
TypeScript
/**
|
|
* ComfyUI Type Definitions
|
|
*
|
|
* Type definitions for ComfyUI's app, canvas, and graph APIs.
|
|
* These types are based on the runtime behavior of ComfyUI.
|
|
*/
|
|
|
|
import type { InfoPanel } from '../info-panel/InfoPanel';
|
|
import type { NodeListEntry } from '../info-panel/NodeSelector';
|
|
import type { PanelAction, PopOutInfo, WidgetEditData, WidgetRef } from '../magnify-glass/PopOutManager';
|
|
|
|
// ============================================================================
|
|
// ComfyUI App
|
|
// ============================================================================
|
|
|
|
export interface ComfyApp {
|
|
graph: ComfyGraph;
|
|
canvas: ComfyCanvas;
|
|
ui: ComfyUI;
|
|
extensionManager: ComfyExtensionManager;
|
|
/** Dispatches the server's execution events */
|
|
api: EventTarget & { apiURL(route: string): string };
|
|
/** Validation errors of the last queued prompt by execution id, null when it had none */
|
|
lastNodeErrors: Record<string, { errors: ComfyNodeError[] }> | null;
|
|
/** Each node's last results by locator id; an image is the query of its /view URL */
|
|
nodeOutputs: Record<string, { images?: Record<string, string>[]; animated?: boolean[] }>;
|
|
/** Blob URLs of the running nodes' live previews, by locator id */
|
|
nodePreviewImages: Record<string, string[]>;
|
|
/** A query parameter that keeps /view responses out of the browser cache, or '' */
|
|
getRandParam(): string;
|
|
registerExtension(extension: ComfyExtension): void;
|
|
}
|
|
|
|
export interface ComfyNodeError {
|
|
message: string;
|
|
details: string;
|
|
extra_info?: { input_name?: string };
|
|
}
|
|
|
|
export interface ComfyExtension {
|
|
name: string;
|
|
setup?: () => Promise<void> | void;
|
|
init?: () => Promise<void> | void;
|
|
afterConfigureGraph?: () => Promise<void> | void;
|
|
commands?: ComfyCommand[];
|
|
keybindings?: ComfyKeybinding[];
|
|
menuCommands?: ComfyMenuCommand[];
|
|
settings?: ComfySetting[];
|
|
bottomPanelTabs?: ComfyBottomPanelTab[];
|
|
aboutPageBadges?: ComfyBadge[];
|
|
getSelectionToolboxCommands?: (selectedItem: unknown) => string[];
|
|
}
|
|
|
|
export interface ComfyCommand {
|
|
id: string;
|
|
label?: string;
|
|
icon?: string;
|
|
function: () => void;
|
|
}
|
|
|
|
export interface ComfyKeybinding {
|
|
combo: {
|
|
key: string;
|
|
alt?: boolean;
|
|
ctrl?: boolean;
|
|
shift?: boolean;
|
|
meta?: boolean;
|
|
};
|
|
commandId: string;
|
|
}
|
|
|
|
export interface ComfyMenuCommand {
|
|
path: string[];
|
|
commands: string[];
|
|
}
|
|
|
|
export interface ComfySetting {
|
|
id: string;
|
|
name: string;
|
|
type: 'text' | 'number' | 'slider' | 'combo' | 'color' | 'boolean';
|
|
defaultValue: unknown;
|
|
min?: number;
|
|
max?: number;
|
|
step?: number;
|
|
options?: Array<{ value: unknown; text: string }>;
|
|
tooltip?: string;
|
|
onChange?: (value: unknown) => void;
|
|
}
|
|
|
|
export interface ComfyBottomPanelTab {
|
|
id: string;
|
|
title: string;
|
|
type: 'custom';
|
|
render: (el: HTMLElement) => void;
|
|
}
|
|
|
|
export interface ComfyBadge {
|
|
label: string;
|
|
url: string;
|
|
icon: string;
|
|
}
|
|
|
|
// ============================================================================
|
|
// ComfyUI UI
|
|
// ============================================================================
|
|
|
|
export interface ComfyUI {
|
|
settings: ComfySettings;
|
|
/** Prompts waiting or running, from the last status event */
|
|
lastQueueSize?: number;
|
|
}
|
|
|
|
export interface ComfySettings {
|
|
addSetting(setting: ComfySetting): void;
|
|
getSettingValue(id: string): unknown;
|
|
setSettingValue(id: string, value: unknown): void;
|
|
}
|
|
|
|
// ============================================================================
|
|
// ComfyUI Extension Manager
|
|
// ============================================================================
|
|
|
|
export interface ComfyExtensionManager {
|
|
setting: {
|
|
get(id: string): unknown;
|
|
set(id: string, value: unknown): void;
|
|
};
|
|
toast: ComfyToast;
|
|
dialog: ComfyDialog;
|
|
/** The open workflow tabs */
|
|
workflow: { activeWorkflow: object | null };
|
|
registerSidebarTab(tab: ComfySidebarTab): void;
|
|
}
|
|
|
|
export interface ComfySidebarTab {
|
|
id: string;
|
|
icon: string;
|
|
title: string;
|
|
tooltip: string;
|
|
type: 'custom';
|
|
render: (el: HTMLElement) => void;
|
|
}
|
|
|
|
export interface ComfyToast {
|
|
add(options: ComfyToastOptions): void;
|
|
addAlert(message: string): void;
|
|
}
|
|
|
|
export interface ComfyToastOptions {
|
|
severity: 'success' | 'info' | 'warn' | 'error';
|
|
summary: string;
|
|
detail: string;
|
|
life?: number;
|
|
}
|
|
|
|
export interface ComfyDialog {
|
|
prompt(options: { title: string; message: string }): Promise<string>;
|
|
confirm(options: { title: string; message: string }): Promise<boolean>;
|
|
}
|
|
|
|
// ============================================================================
|
|
// ComfyUI Graph
|
|
// ============================================================================
|
|
|
|
export interface ComfyGraph {
|
|
_nodes: ComfyNode[];
|
|
id: string;
|
|
/** The graph itself for the root graph; set on subgraphs */
|
|
rootGraph: ComfyGraph;
|
|
/** Subgraphs only */
|
|
name?: string;
|
|
/** Subgraphs only: the slots of its own input and output nodes */
|
|
inputs?: ComfySlot[];
|
|
outputs?: ComfySlot[];
|
|
links: Map<number, ComfyLink>;
|
|
getNodeById(id: number): ComfyNode | null;
|
|
getNodeOnPos(x: number, y: number): ComfyNode | null;
|
|
getGroupOnPos(x: number, y: number): { title: string } | undefined;
|
|
}
|
|
|
|
export interface ComfyNode {
|
|
id: number;
|
|
title: string;
|
|
type: string;
|
|
mode: number;
|
|
pos: [number, number];
|
|
size: [number, number];
|
|
flags?: {
|
|
collapsed?: boolean;
|
|
};
|
|
widgets?: ComfyWidget[];
|
|
inputs?: ComfySlot[];
|
|
outputs?: ComfySlot[];
|
|
properties?: Record<string, unknown>;
|
|
graph?: ComfyGraph;
|
|
/** Subgraph nodes only */
|
|
subgraph?: ComfyGraph;
|
|
isSubgraphNode?(): boolean;
|
|
getInputNode(slot: number): ComfyNode | null;
|
|
}
|
|
|
|
export interface ComfyWidget {
|
|
name: string;
|
|
type: string;
|
|
value: unknown;
|
|
options?: Record<string, unknown>;
|
|
min?: number;
|
|
max?: number;
|
|
step?: number;
|
|
}
|
|
|
|
export interface ComfySlot {
|
|
name: string;
|
|
label?: string;
|
|
localized_name?: string;
|
|
type: string;
|
|
link?: number | null;
|
|
links?: number[];
|
|
/** Inputs a widget sets until they are linked */
|
|
widget?: { name: string };
|
|
}
|
|
|
|
export interface ComfyLink {
|
|
origin_id: number;
|
|
origin_slot: number;
|
|
target_id: number;
|
|
target_slot: number;
|
|
}
|
|
|
|
// ============================================================================
|
|
// ComfyUI Canvas
|
|
// ============================================================================
|
|
|
|
export interface ComfyCanvas {
|
|
canvas: HTMLCanvasElement;
|
|
graph: ComfyGraph | null;
|
|
ds: {
|
|
scale: number;
|
|
offset: [number, number];
|
|
};
|
|
node_over: ComfyNode | null;
|
|
/** True in pan mode: space held or the hand tool */
|
|
read_only: boolean;
|
|
selected_nodes: Record<string, ComfyNode>;
|
|
convertOffsetToCanvasPos?(pos: [number, number]): [number, number];
|
|
centerOnNode(node: ComfyNode): void;
|
|
openSubgraph(subgraph: ComfyGraph, fromNode: ComfyNode): void;
|
|
}
|
|
|
|
// ============================================================================
|
|
// Global Window Extensions
|
|
// ============================================================================
|
|
|
|
declare global {
|
|
interface Window {
|
|
comfyUIMagnifyGlass?: MagnifyGlassInstance;
|
|
comfyUIMagnifyGlassExtensions?: InfoPanel[];
|
|
infoPanelManager?: InfoPanel;
|
|
}
|
|
|
|
var app: ComfyApp;
|
|
/** package.json's version, set by vite at build time */
|
|
const __MAGNIFY_VERSION__: string;
|
|
}
|
|
|
|
export interface MagnifyGlassInstance {
|
|
state: MagnifyGlassState;
|
|
config: MagnifyGlassConfig;
|
|
ui: MagnifyGlassUI;
|
|
renderer: MagnifyGlassRenderer | null;
|
|
popOutManager?: {
|
|
isPopOutOpen(): boolean;
|
|
sendInfo(info: PopOutInfo): void;
|
|
toggle(): void;
|
|
onStateChange?: ((isOpen: boolean) => void) | null;
|
|
onNodeSelect?: ((nodeId: number) => void) | null;
|
|
onWidgetEdit?: ((data: WidgetEditData) => void) | null;
|
|
onButtonClick?: ((data: WidgetRef) => void) | null;
|
|
onPanelAction?: ((name: PanelAction, nodeId: number | null) => void) | null;
|
|
onRequestOptions?: ((data: WidgetRef) => unknown[]) | null;
|
|
onSearchNodes?: ((query: string) => NodeListEntry[]) | null;
|
|
};
|
|
lastKnownMousePosition: { x: number; y: number };
|
|
updateMagnifiedView(): void;
|
|
applyUiChanges(): void;
|
|
toggle(): void;
|
|
resetOffsets(): void;
|
|
setGlassPreviewActive(visible: boolean): void;
|
|
}
|
|
|
|
export interface MagnifyGlassState {
|
|
active: boolean;
|
|
x: number;
|
|
y: number;
|
|
sourceX: number;
|
|
sourceY: number;
|
|
sourceWidth: number;
|
|
sourceHeight: number;
|
|
canvasScale: number;
|
|
canvasOffsetX: number;
|
|
canvasOffsetY: number;
|
|
}
|
|
|
|
export interface MagnifyGlassConfig {
|
|
zoomFactor: number;
|
|
glassSize: number;
|
|
borderColor: string;
|
|
borderWidth: number;
|
|
borderEnabled: boolean;
|
|
activationKey: string;
|
|
altRequired: boolean;
|
|
followCursor: boolean;
|
|
offsetStep: number;
|
|
offsetX: number;
|
|
offsetY: number;
|
|
glassPosition: string;
|
|
glassShape: string;
|
|
resetKey: string;
|
|
textureFiltering: string;
|
|
alwaysActiveMode: boolean;
|
|
toggleFollowCursorKey: string;
|
|
}
|
|
|
|
export interface MagnifyGlassUI {
|
|
glassDiv: HTMLDivElement | null;
|
|
show(): void;
|
|
hide(): void;
|
|
positionGlass(x: number, y: number): void;
|
|
}
|
|
|
|
export interface MagnifyGlassRenderer {
|
|
updateTextureFiltering(filtering: string): void;
|
|
}
|
|
|
|
// ============================================================================
|
|
// Info Panel Types
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Detailed information about a node.
|
|
* Structure matches InformationGatherer.getDetailedNodeInfo() output.
|
|
*/
|
|
export interface NodeInfo {
|
|
id: number;
|
|
title: string;
|
|
type: string;
|
|
mode: string;
|
|
position: {
|
|
x: number;
|
|
y: number;
|
|
};
|
|
size: {
|
|
width: number;
|
|
height: number;
|
|
};
|
|
widgets: ComfyWidget[];
|
|
inputs: ComfyInput[];
|
|
outputs: ComfyOutput[];
|
|
properties: Record<string, unknown>;
|
|
executionOrder?: number;
|
|
category?: string;
|
|
pythonModule?: string;
|
|
/** Names of the subgraphs from the root down to the node's graph */
|
|
graphPath: string[];
|
|
/** The id the server runs the node by: the ids of the subgraph nodes it is in, then its own, joined by ':' */
|
|
executionId: string;
|
|
/** The id ComfyUI keeps the node's outputs by: its subgraph's id and its own, joined by ':', or its own in the root graph */
|
|
locatorId: string;
|
|
group?: string;
|
|
isSubgraph: boolean;
|
|
}
|
|
|
|
export { };
|
|
|