@happyvertical/comfyui 0.74.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT.md +33 -0
- package/LICENSE +7 -0
- package/README.md +283 -0
- package/dist/index.d.ts +506 -0
- package/dist/index.js +478 -0
- package/dist/index.js.map +1 -0
- package/metadata.json +29 -0
- package/package.json +54 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @happyvertical/comfyui
|
|
3
|
+
*
|
|
4
|
+
* ComfyUI API client for workflow orchestration and video generation.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { ComfyUIClient, injectWorkflowParams } from '@happyvertical/comfyui';
|
|
9
|
+
*
|
|
10
|
+
* // Create client
|
|
11
|
+
* const client = new ComfyUIClient({
|
|
12
|
+
* url: 'http://localhost:8188',
|
|
13
|
+
* });
|
|
14
|
+
*
|
|
15
|
+
* // Connect and execute workflow
|
|
16
|
+
* await client.connect();
|
|
17
|
+
*
|
|
18
|
+
* const workflow = await loadWorkflow('my-workflow.json');
|
|
19
|
+
* const modifiedWorkflow = injectWorkflowParams(workflow, {
|
|
20
|
+
* seedImage: '3',
|
|
21
|
+
* prompt: '6',
|
|
22
|
+
* }, {
|
|
23
|
+
* seedImage: 'input/anchor.png',
|
|
24
|
+
* prompt: 'professional news anchor speaking',
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* const result = await client.queuePrompt(modifiedWorkflow);
|
|
28
|
+
*
|
|
29
|
+
* // Wait for completion with progress updates
|
|
30
|
+
* const history = await client.waitForCompletion(result.promptId, {
|
|
31
|
+
* onProgress: (event) => {
|
|
32
|
+
* if (event.type === 'progress') {
|
|
33
|
+
* console.log(`Progress: ${event.value}/${event.max}`);
|
|
34
|
+
* }
|
|
35
|
+
* },
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* // Download output
|
|
39
|
+
* const output = history.outputs['SaveVideo'];
|
|
40
|
+
* if (output?.videos?.[0]) {
|
|
41
|
+
* const video = await client.downloadOutput(output.videos[0].filename);
|
|
42
|
+
* fs.writeFileSync('output.mp4', video);
|
|
43
|
+
* }
|
|
44
|
+
*
|
|
45
|
+
* await client.disconnect();
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @packageDocumentation
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* A single node in a ComfyUI workflow
|
|
53
|
+
*/
|
|
54
|
+
export declare interface ComfyNode {
|
|
55
|
+
/**
|
|
56
|
+
* Node class type (e.g., 'KSampler', 'LoadImage', 'SaveImage')
|
|
57
|
+
*/
|
|
58
|
+
class_type: string;
|
|
59
|
+
/**
|
|
60
|
+
* Node input values
|
|
61
|
+
*/
|
|
62
|
+
inputs: Record<string, unknown>;
|
|
63
|
+
/**
|
|
64
|
+
* Optional metadata
|
|
65
|
+
*/
|
|
66
|
+
_meta?: {
|
|
67
|
+
title?: string;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* ComfyUI client for workflow execution and management
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* import { ComfyUIClient } from '@happyvertical/comfyui';
|
|
77
|
+
*
|
|
78
|
+
* const client = new ComfyUIClient({
|
|
79
|
+
* url: 'http://localhost:8188',
|
|
80
|
+
* });
|
|
81
|
+
*
|
|
82
|
+
* await client.connect();
|
|
83
|
+
*
|
|
84
|
+
* const result = await client.queuePrompt(workflow);
|
|
85
|
+
* await client.waitForCompletion(result.promptId, {
|
|
86
|
+
* onProgress: (event) => console.log(`Progress: ${event.value}%`),
|
|
87
|
+
* });
|
|
88
|
+
*
|
|
89
|
+
* const output = await client.downloadOutput('video.mp4');
|
|
90
|
+
* await client.disconnect();
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
export declare class ComfyUIClient {
|
|
94
|
+
private options;
|
|
95
|
+
private ws;
|
|
96
|
+
private logger;
|
|
97
|
+
private clientId;
|
|
98
|
+
private messageHandlers;
|
|
99
|
+
private reconnectAttempts;
|
|
100
|
+
private isConnecting;
|
|
101
|
+
private username?;
|
|
102
|
+
private password?;
|
|
103
|
+
constructor(options?: ComfyUIClientOptions);
|
|
104
|
+
/**
|
|
105
|
+
* Get the HTTP base URL
|
|
106
|
+
*/
|
|
107
|
+
private get httpUrl();
|
|
108
|
+
/**
|
|
109
|
+
* Get the WebSocket URL
|
|
110
|
+
*/
|
|
111
|
+
private get wsUrl();
|
|
112
|
+
/**
|
|
113
|
+
* Connect to the ComfyUI WebSocket
|
|
114
|
+
*/
|
|
115
|
+
connect(): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Establish WebSocket connection
|
|
118
|
+
*/
|
|
119
|
+
private establishConnection;
|
|
120
|
+
/**
|
|
121
|
+
* Handle WebSocket disconnection
|
|
122
|
+
*/
|
|
123
|
+
private handleDisconnect;
|
|
124
|
+
/**
|
|
125
|
+
* Handle incoming WebSocket messages
|
|
126
|
+
*/
|
|
127
|
+
private handleMessage;
|
|
128
|
+
/**
|
|
129
|
+
* Parse a WebSocket message into a ProgressEvent
|
|
130
|
+
*/
|
|
131
|
+
private parseProgressEvent;
|
|
132
|
+
/**
|
|
133
|
+
* Disconnect from ComfyUI
|
|
134
|
+
*/
|
|
135
|
+
disconnect(): Promise<void>;
|
|
136
|
+
/**
|
|
137
|
+
* Make an HTTP request to ComfyUI
|
|
138
|
+
*/
|
|
139
|
+
private request;
|
|
140
|
+
/**
|
|
141
|
+
* Queue a workflow for execution
|
|
142
|
+
*
|
|
143
|
+
* @param workflow - The ComfyUI workflow to execute
|
|
144
|
+
* @param clientId - Optional client ID (uses default if not provided)
|
|
145
|
+
* @returns Promise resolving to prompt result with ID
|
|
146
|
+
*/
|
|
147
|
+
queuePrompt(workflow: ComfyWorkflow, clientId?: string): Promise<PromptResult>;
|
|
148
|
+
/**
|
|
149
|
+
* Subscribe to progress events for a prompt
|
|
150
|
+
*
|
|
151
|
+
* @param promptId - The prompt ID to monitor
|
|
152
|
+
* @param handler - Callback for progress events
|
|
153
|
+
* @returns Unsubscribe function
|
|
154
|
+
*/
|
|
155
|
+
onProgress(promptId: string, handler: (event: ProgressEvent_2) => void): () => void;
|
|
156
|
+
/**
|
|
157
|
+
* Wait for a prompt to complete
|
|
158
|
+
*
|
|
159
|
+
* @param promptId - The prompt ID to wait for
|
|
160
|
+
* @param options - Wait options including progress callback
|
|
161
|
+
* @returns Promise resolving to the history entry
|
|
162
|
+
*/
|
|
163
|
+
waitForCompletion(promptId: string, options?: WaitOptions): Promise<HistoryEntry>;
|
|
164
|
+
/**
|
|
165
|
+
* Get history for a specific prompt
|
|
166
|
+
*
|
|
167
|
+
* @param promptId - The prompt ID to get history for
|
|
168
|
+
* @returns Promise resolving to the history entry
|
|
169
|
+
*/
|
|
170
|
+
getHistory(promptId: string): Promise<HistoryEntry>;
|
|
171
|
+
/**
|
|
172
|
+
* Download an output file from ComfyUI
|
|
173
|
+
*
|
|
174
|
+
* @param filename - Name of the file to download
|
|
175
|
+
* @param subfolder - Subfolder where file is located
|
|
176
|
+
* @param type - Type of file location ('output', 'temp', or 'input')
|
|
177
|
+
* @returns Promise resolving to the file buffer
|
|
178
|
+
*/
|
|
179
|
+
downloadOutput(filename: string, subfolder?: string, type?: 'output' | 'temp' | 'input'): Promise<Buffer>;
|
|
180
|
+
/**
|
|
181
|
+
* Upload a file to ComfyUI
|
|
182
|
+
*
|
|
183
|
+
* @param file - File buffer to upload
|
|
184
|
+
* @param filename - Name for the file
|
|
185
|
+
* @param type - Where to upload ('input' or 'temp')
|
|
186
|
+
* @param overwrite - Whether to overwrite existing file
|
|
187
|
+
* @returns Promise resolving to upload result
|
|
188
|
+
*/
|
|
189
|
+
uploadFile(file: Buffer, filename: string, type?: 'input' | 'temp', overwrite?: boolean): Promise<UploadResult>;
|
|
190
|
+
/**
|
|
191
|
+
* Get system statistics from ComfyUI
|
|
192
|
+
*
|
|
193
|
+
* @returns Promise resolving to system stats
|
|
194
|
+
*/
|
|
195
|
+
getSystemStats(): Promise<SystemStats>;
|
|
196
|
+
/**
|
|
197
|
+
* Get the current queue status
|
|
198
|
+
*
|
|
199
|
+
* @returns Promise resolving to queue status
|
|
200
|
+
*/
|
|
201
|
+
getQueue(): Promise<QueueStatus>;
|
|
202
|
+
/**
|
|
203
|
+
* Interrupt the current execution
|
|
204
|
+
*/
|
|
205
|
+
interrupt(): Promise<void>;
|
|
206
|
+
/**
|
|
207
|
+
* Clear the execution queue
|
|
208
|
+
*/
|
|
209
|
+
clearQueue(): Promise<void>;
|
|
210
|
+
/**
|
|
211
|
+
* Delete a specific item from the queue
|
|
212
|
+
*
|
|
213
|
+
* @param promptId - The prompt ID to delete
|
|
214
|
+
*/
|
|
215
|
+
deleteFromQueue(promptId: string): Promise<void>;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Configuration for the ComfyUI client
|
|
220
|
+
*/
|
|
221
|
+
export declare interface ComfyUIClientOptions {
|
|
222
|
+
/**
|
|
223
|
+
* Base URL for the ComfyUI server
|
|
224
|
+
* @default 'http://localhost:8188'
|
|
225
|
+
*/
|
|
226
|
+
url?: string;
|
|
227
|
+
/**
|
|
228
|
+
* Request timeout in milliseconds
|
|
229
|
+
* @default 600000 (10 minutes)
|
|
230
|
+
*/
|
|
231
|
+
timeout?: number;
|
|
232
|
+
/**
|
|
233
|
+
* Custom headers for API requests
|
|
234
|
+
*/
|
|
235
|
+
headers?: Record<string, string>;
|
|
236
|
+
/**
|
|
237
|
+
* Reconnection options for WebSocket
|
|
238
|
+
*/
|
|
239
|
+
reconnect?: Partial<ReconnectOptions>;
|
|
240
|
+
/**
|
|
241
|
+
* Username for HTTP Basic authentication
|
|
242
|
+
*/
|
|
243
|
+
username?: string;
|
|
244
|
+
/**
|
|
245
|
+
* Password for HTTP Basic authentication
|
|
246
|
+
*/
|
|
247
|
+
password?: string;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* ComfyUI workflow definition (API format JSON)
|
|
252
|
+
*/
|
|
253
|
+
export declare interface ComfyWorkflow {
|
|
254
|
+
/**
|
|
255
|
+
* Node definitions in the workflow
|
|
256
|
+
* Keys are node IDs
|
|
257
|
+
*/
|
|
258
|
+
[nodeId: string]: ComfyNode;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* History entry for a completed prompt
|
|
263
|
+
*/
|
|
264
|
+
export declare interface HistoryEntry {
|
|
265
|
+
/**
|
|
266
|
+
* Prompt ID
|
|
267
|
+
*/
|
|
268
|
+
promptId: string;
|
|
269
|
+
/**
|
|
270
|
+
* Status of the execution
|
|
271
|
+
*/
|
|
272
|
+
status: {
|
|
273
|
+
completed: boolean;
|
|
274
|
+
status_str: string;
|
|
275
|
+
messages: Array<[string, unknown]>;
|
|
276
|
+
};
|
|
277
|
+
/**
|
|
278
|
+
* Output data from each node
|
|
279
|
+
*/
|
|
280
|
+
outputs: Record<string, NodeOutput>;
|
|
281
|
+
/**
|
|
282
|
+
* Original prompt data
|
|
283
|
+
*/
|
|
284
|
+
prompt: [number, string, ComfyWorkflow, any, string[]];
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Helper function to inject parameters into a workflow
|
|
289
|
+
*
|
|
290
|
+
* @param workflow - The base workflow
|
|
291
|
+
* @param mapping - Node mapping defining where to inject
|
|
292
|
+
* @param values - Values to inject
|
|
293
|
+
* @returns Modified workflow with injected values
|
|
294
|
+
*/
|
|
295
|
+
export declare function injectWorkflowParams(workflow: ComfyWorkflow, mapping: NodeMapping, values: Record<string, any>): ComfyWorkflow;
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Node mapping for dynamic parameter injection
|
|
299
|
+
*/
|
|
300
|
+
export declare interface NodeMapping {
|
|
301
|
+
/**
|
|
302
|
+
* Node ID for seed image input
|
|
303
|
+
*/
|
|
304
|
+
seedImage?: string;
|
|
305
|
+
/**
|
|
306
|
+
* Node ID for audio file input
|
|
307
|
+
*/
|
|
308
|
+
audioFile?: string;
|
|
309
|
+
/**
|
|
310
|
+
* Node ID for base video input
|
|
311
|
+
*/
|
|
312
|
+
baseVideo?: string;
|
|
313
|
+
/**
|
|
314
|
+
* Node ID for final output
|
|
315
|
+
*/
|
|
316
|
+
outputVideo?: string;
|
|
317
|
+
/**
|
|
318
|
+
* Node ID for text prompt input
|
|
319
|
+
*/
|
|
320
|
+
prompt?: string;
|
|
321
|
+
/**
|
|
322
|
+
* Node ID for negative prompt input
|
|
323
|
+
*/
|
|
324
|
+
negativePrompt?: string;
|
|
325
|
+
/**
|
|
326
|
+
* Additional custom mappings
|
|
327
|
+
*/
|
|
328
|
+
[key: string]: string | undefined;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Output data from a single node
|
|
333
|
+
*/
|
|
334
|
+
export declare interface NodeOutput {
|
|
335
|
+
/**
|
|
336
|
+
* Images produced by this node
|
|
337
|
+
*/
|
|
338
|
+
images?: Array<{
|
|
339
|
+
filename: string;
|
|
340
|
+
subfolder: string;
|
|
341
|
+
type: 'output' | 'temp' | 'input';
|
|
342
|
+
}>;
|
|
343
|
+
/**
|
|
344
|
+
* Other output data
|
|
345
|
+
*/
|
|
346
|
+
[key: string]: unknown;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Progress event during workflow execution
|
|
351
|
+
*/
|
|
352
|
+
declare interface ProgressEvent_2 {
|
|
353
|
+
/**
|
|
354
|
+
* Type of progress event
|
|
355
|
+
*/
|
|
356
|
+
type: 'executing' | 'progress' | 'execution_cached' | 'executed' | 'execution_error';
|
|
357
|
+
/**
|
|
358
|
+
* Currently executing node ID
|
|
359
|
+
*/
|
|
360
|
+
nodeId?: string;
|
|
361
|
+
/**
|
|
362
|
+
* Progress value (0-100 for 'progress' type)
|
|
363
|
+
*/
|
|
364
|
+
value?: number;
|
|
365
|
+
/**
|
|
366
|
+
* Maximum value for progress
|
|
367
|
+
*/
|
|
368
|
+
max?: number;
|
|
369
|
+
/**
|
|
370
|
+
* Prompt ID this event relates to
|
|
371
|
+
*/
|
|
372
|
+
promptId?: string;
|
|
373
|
+
/**
|
|
374
|
+
* Output data for completed nodes
|
|
375
|
+
*/
|
|
376
|
+
output?: Record<string, unknown>;
|
|
377
|
+
/**
|
|
378
|
+
* Error message (for 'execution_error' type)
|
|
379
|
+
*/
|
|
380
|
+
error?: string;
|
|
381
|
+
}
|
|
382
|
+
export { ProgressEvent_2 as ProgressEvent }
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Result from queueing a prompt
|
|
386
|
+
*/
|
|
387
|
+
export declare interface PromptResult {
|
|
388
|
+
/**
|
|
389
|
+
* Unique ID for this prompt execution
|
|
390
|
+
*/
|
|
391
|
+
promptId: string;
|
|
392
|
+
/**
|
|
393
|
+
* Queue number position
|
|
394
|
+
*/
|
|
395
|
+
number: number;
|
|
396
|
+
/**
|
|
397
|
+
* Node-specific errors (if any)
|
|
398
|
+
*/
|
|
399
|
+
nodeErrors?: Record<string, string[]>;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Queue status from ComfyUI
|
|
404
|
+
*/
|
|
405
|
+
export declare interface QueueStatus {
|
|
406
|
+
/**
|
|
407
|
+
* Currently running prompts
|
|
408
|
+
*/
|
|
409
|
+
running: Array<[number, string, ComfyWorkflow, any]>;
|
|
410
|
+
/**
|
|
411
|
+
* Pending prompts in queue
|
|
412
|
+
*/
|
|
413
|
+
pending: Array<[number, string, ComfyWorkflow, any]>;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* ComfyUI API Types
|
|
418
|
+
*
|
|
419
|
+
* Types for interacting with ComfyUI's REST and WebSocket APIs.
|
|
420
|
+
*/
|
|
421
|
+
/**
|
|
422
|
+
* Reconnection options for WebSocket
|
|
423
|
+
*/
|
|
424
|
+
declare interface ReconnectOptions {
|
|
425
|
+
/**
|
|
426
|
+
* Whether to automatically reconnect
|
|
427
|
+
* @default true
|
|
428
|
+
*/
|
|
429
|
+
enabled: boolean;
|
|
430
|
+
/**
|
|
431
|
+
* Maximum number of reconnection attempts
|
|
432
|
+
* @default 5
|
|
433
|
+
*/
|
|
434
|
+
maxAttempts: number;
|
|
435
|
+
/**
|
|
436
|
+
* Delay between reconnection attempts in ms
|
|
437
|
+
* @default 1000
|
|
438
|
+
*/
|
|
439
|
+
delay: number;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* System information from ComfyUI
|
|
444
|
+
*/
|
|
445
|
+
export declare interface SystemStats {
|
|
446
|
+
/**
|
|
447
|
+
* Available CUDA devices
|
|
448
|
+
*/
|
|
449
|
+
devices: Array<{
|
|
450
|
+
name: string;
|
|
451
|
+
type: string;
|
|
452
|
+
index: number;
|
|
453
|
+
vram_total: number;
|
|
454
|
+
vram_free: number;
|
|
455
|
+
torch_vram_total: number;
|
|
456
|
+
torch_vram_free: number;
|
|
457
|
+
}>;
|
|
458
|
+
/**
|
|
459
|
+
* System RAM information
|
|
460
|
+
*/
|
|
461
|
+
system: {
|
|
462
|
+
os: string;
|
|
463
|
+
python_version: string;
|
|
464
|
+
embedded_python: boolean;
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* File upload result
|
|
470
|
+
*/
|
|
471
|
+
export declare interface UploadResult {
|
|
472
|
+
/**
|
|
473
|
+
* Name of the uploaded file
|
|
474
|
+
*/
|
|
475
|
+
name: string;
|
|
476
|
+
/**
|
|
477
|
+
* Subfolder where file was uploaded
|
|
478
|
+
*/
|
|
479
|
+
subfolder: string;
|
|
480
|
+
/**
|
|
481
|
+
* Type of upload location
|
|
482
|
+
*/
|
|
483
|
+
type: 'input' | 'temp' | 'output';
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Options for waiting on prompt completion
|
|
488
|
+
*/
|
|
489
|
+
export declare interface WaitOptions {
|
|
490
|
+
/**
|
|
491
|
+
* Callback for progress updates
|
|
492
|
+
*/
|
|
493
|
+
onProgress?: (event: ProgressEvent_2) => void;
|
|
494
|
+
/**
|
|
495
|
+
* Timeout in milliseconds (0 = no timeout)
|
|
496
|
+
* @default 600000 (10 minutes)
|
|
497
|
+
*/
|
|
498
|
+
timeout?: number;
|
|
499
|
+
/**
|
|
500
|
+
* Polling interval for fallback HTTP polling (if WebSocket fails)
|
|
501
|
+
* @default 1000
|
|
502
|
+
*/
|
|
503
|
+
pollInterval?: number;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
export { }
|