Files
AEmotionStudio-ComfyUI-Magn…/src/types/comfyui.d.ts
T
Æmotion StudioandClaude Opus 5.5 7852897c1d Add Inputs and Outputs links to the pop-out viewer
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>
2026-11-04 10:14:49 -08:00

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 { };