comfyui-node 1.6.2 → 1.6.3

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.
Files changed (49) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/index.d.ts +18 -13
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +10 -7
  5. package/dist/index.js.map +1 -1
  6. package/dist/multipool/client-registry.js +152 -152
  7. package/dist/multipool/helpers.js +52 -52
  8. package/dist/multipool/helpers.js.map +1 -1
  9. package/dist/multipool/index.js +2 -2
  10. package/dist/multipool/interfaces.d.ts +29 -12
  11. package/dist/multipool/interfaces.d.ts.map +1 -1
  12. package/dist/multipool/interfaces.js +1 -1
  13. package/dist/multipool/job-state-registry.js +282 -282
  14. package/dist/multipool/multi-workflow-pool.d.ts +102 -42
  15. package/dist/multipool/multi-workflow-pool.d.ts.map +1 -1
  16. package/dist/multipool/multi-workflow-pool.js +424 -313
  17. package/dist/multipool/multi-workflow-pool.js.map +1 -1
  18. package/dist/multipool/pool-event-manager.js +27 -27
  19. package/dist/multipool/tests/client-registry-api-demo.d.ts +7 -0
  20. package/dist/multipool/tests/client-registry-api-demo.d.ts.map +1 -0
  21. package/dist/multipool/tests/client-registry-api-demo.js +136 -0
  22. package/dist/multipool/tests/client-registry-api-demo.js.map +1 -0
  23. package/dist/multipool/tests/client-registry.spec.d.ts +2 -0
  24. package/dist/multipool/tests/client-registry.spec.d.ts.map +1 -0
  25. package/dist/multipool/tests/client-registry.spec.js +191 -0
  26. package/dist/multipool/tests/client-registry.spec.js.map +1 -0
  27. package/dist/multipool/tests/error-classification-tests.js +373 -373
  28. package/dist/multipool/tests/event-forwarding-demo.d.ts +7 -0
  29. package/dist/multipool/tests/event-forwarding-demo.d.ts.map +1 -0
  30. package/dist/multipool/tests/event-forwarding-demo.js +88 -0
  31. package/dist/multipool/tests/event-forwarding-demo.js.map +1 -0
  32. package/dist/multipool/tests/helpers.spec.d.ts +2 -0
  33. package/dist/multipool/tests/helpers.spec.d.ts.map +1 -0
  34. package/dist/multipool/tests/helpers.spec.js +100 -0
  35. package/dist/multipool/tests/helpers.spec.js.map +1 -0
  36. package/dist/multipool/tests/job-queue-processor.spec.d.ts +2 -0
  37. package/dist/multipool/tests/job-queue-processor.spec.d.ts.map +1 -0
  38. package/dist/multipool/tests/job-queue-processor.spec.js +89 -0
  39. package/dist/multipool/tests/job-queue-processor.spec.js.map +1 -0
  40. package/dist/multipool/tests/job-state-registry.spec.d.ts +2 -0
  41. package/dist/multipool/tests/job-state-registry.spec.d.ts.map +1 -0
  42. package/dist/multipool/tests/job-state-registry.spec.js +143 -0
  43. package/dist/multipool/tests/job-state-registry.spec.js.map +1 -0
  44. package/dist/multipool/tests/multipool-basic.js +141 -141
  45. package/dist/multipool/tests/profiling-demo.js +87 -87
  46. package/dist/multipool/tests/profiling-demo.js.map +1 -1
  47. package/dist/multipool/tests/two-stage-edit-simulation.js +298 -298
  48. package/dist/multipool/tests/two-stage-edit-simulation.js.map +1 -1
  49. package/package.json +1 -1
@@ -1,374 +1,374 @@
1
- import { MultiWorkflowPool } from "src/multipool/multi-workflow-pool.js";
2
- import { Workflow } from "src/multipool/workflow.js";
3
- /**
4
- * Error Classification Validation Tests
5
- *
6
- * This script validates the error classification logic by intentionally triggering
7
- * different types of errors from real ComfyUI servers.
8
- *
9
- * Test Cases:
10
- * 1. Missing Model Error (workflow_incompatibility)
11
- * 2. Missing Custom Node Error (workflow_incompatibility)
12
- * 3. Invalid Input Error (transient)
13
- * 4. Connection Error (connection)
14
- */
15
- const pool = new MultiWorkflowPool();
16
- // Add your real ComfyUI servers here
17
- pool.addClient("http://server1:8188", {
18
- workflowAffinity: [],
19
- priority: 1
20
- });
21
- pool.addClient("http://server2:8188", {
22
- workflowAffinity: [],
23
- priority: 1
24
- });
25
- pool.addClient("http://server3:8188", {
26
- workflowAffinity: [],
27
- priority: 1
28
- });
29
- await pool.init();
30
- console.log("\n" + "=".repeat(80));
31
- console.log("ERROR CLASSIFICATION VALIDATION TESTS");
32
- console.log("=".repeat(80) + "\n");
33
- // ============================================================================
34
- // TEST 1: Missing Model Error (should be classified as workflow_incompatibility)
35
- // ============================================================================
36
- async function testMissingModel() {
37
- console.log("\nšŸ“‹ TEST 1: Missing Model Error");
38
- console.log("-".repeat(80));
39
- const workflow = new Workflow({
40
- "1": {
41
- "inputs": {
42
- "text": "beautiful landscape"
43
- },
44
- "class_type": "CLIPTextEncode",
45
- "_meta": {
46
- "title": "CLIP Text Encode (Prompt)"
47
- }
48
- },
49
- "2": {
50
- "inputs": {
51
- "ckpt_name": "this_model_definitely_does_not_exist_anywhere_12345.safetensors"
52
- },
53
- "class_type": "CheckpointLoaderSimple",
54
- "_meta": {
55
- "title": "Load Checkpoint"
56
- }
57
- },
58
- "3": {
59
- "inputs": {
60
- "seed": 12345,
61
- "steps": 20,
62
- "cfg": 7.0,
63
- "sampler_name": "euler",
64
- "scheduler": "normal",
65
- "denoise": 1.0,
66
- "model": ["2", 0],
67
- "positive": ["1", 0],
68
- "negative": ["1", 0],
69
- "latent_image": ["4", 0]
70
- },
71
- "class_type": "KSampler",
72
- "_meta": {
73
- "title": "KSampler"
74
- }
75
- },
76
- "4": {
77
- "inputs": {
78
- "width": 512,
79
- "height": 512,
80
- "batch_size": 1
81
- },
82
- "class_type": "EmptyLatentImage",
83
- "_meta": {
84
- "title": "Empty Latent Image"
85
- }
86
- },
87
- "5": {
88
- "inputs": {
89
- "samples": ["3", 0],
90
- "vae": ["2", 2]
91
- },
92
- "class_type": "VAEDecode",
93
- "_meta": {
94
- "title": "VAE Decode"
95
- }
96
- },
97
- "6": {
98
- "inputs": {
99
- "filename_prefix": "ComfyUI",
100
- "images": ["5", 0]
101
- },
102
- "class_type": "SaveImage",
103
- "_meta": {
104
- "title": "Save Image"
105
- }
106
- }
107
- });
108
- try {
109
- const jobId = await pool.submitJob(workflow);
110
- console.log(`Submitted job: ${jobId}`);
111
- const result = await pool.waitForJobCompletion(jobId);
112
- if (result.status === "failed") {
113
- console.log("āœ… Test PASSED: Job failed as expected");
114
- console.log(`Error classification should be: workflow_incompatibility`);
115
- console.log(`Actual error:`, result.error);
116
- }
117
- else {
118
- console.log("āŒ Test FAILED: Job should have failed but didn't");
119
- }
120
- }
121
- catch (error) {
122
- console.log("āŒ Test ERROR:", error);
123
- }
124
- }
125
- // ============================================================================
126
- // TEST 2: Missing Custom Node Error (should be classified as workflow_incompatibility)
127
- // ============================================================================
128
- async function testMissingCustomNode() {
129
- console.log("\nšŸ“‹ TEST 2: Missing Custom Node Error");
130
- console.log("-".repeat(80));
131
- const workflow = new Workflow({
132
- "1": {
133
- "inputs": {
134
- "some_input": "test"
135
- },
136
- "class_type": "NonExistentCustomNode_XYZ_12345",
137
- "_meta": {
138
- "title": "This Node Does Not Exist"
139
- }
140
- },
141
- "2": {
142
- "inputs": {
143
- "filename_prefix": "test",
144
- "images": ["1", 0]
145
- },
146
- "class_type": "SaveImage",
147
- "_meta": {
148
- "title": "Save Image"
149
- }
150
- }
151
- });
152
- try {
153
- const jobId = await pool.submitJob(workflow);
154
- console.log(`Submitted job: ${jobId}`);
155
- const result = await pool.waitForJobCompletion(jobId);
156
- if (result.status === "failed") {
157
- console.log("āœ… Test PASSED: Job failed as expected");
158
- console.log(`Error classification should be: workflow_incompatibility`);
159
- console.log(`Actual error:`, result.error);
160
- }
161
- else {
162
- console.log("āŒ Test FAILED: Job should have failed but didn't");
163
- }
164
- }
165
- catch (error) {
166
- console.log("āŒ Test ERROR:", error);
167
- }
168
- }
169
- // ============================================================================
170
- // TEST 3: Invalid Input Error (should be classified as transient)
171
- // ============================================================================
172
- async function testInvalidInput() {
173
- console.log("\nšŸ“‹ TEST 3: Invalid Input Error");
174
- console.log("-".repeat(80));
175
- const workflow = new Workflow({
176
- "1": {
177
- "inputs": {
178
- "width": -999999, // Negative width should cause validation error
179
- "height": -999999, // Negative height should cause validation error
180
- "batch_size": 1
181
- },
182
- "class_type": "EmptyLatentImage",
183
- "_meta": {
184
- "title": "Empty Latent Image"
185
- }
186
- },
187
- "2": {
188
- "inputs": {
189
- "filename_prefix": "test",
190
- "images": ["1", 0]
191
- },
192
- "class_type": "SaveImage",
193
- "_meta": {
194
- "title": "Save Image"
195
- }
196
- }
197
- });
198
- try {
199
- const jobId = await pool.submitJob(workflow);
200
- console.log(`Submitted job: ${jobId}`);
201
- const result = await pool.waitForJobCompletion(jobId);
202
- if (result.status === "failed") {
203
- console.log("āœ… Test PASSED: Job failed as expected");
204
- console.log(`Error classification should be: transient`);
205
- console.log(`Actual error:`, result.error);
206
- }
207
- else {
208
- console.log("āŒ Test FAILED: Job should have failed but didn't");
209
- }
210
- }
211
- catch (error) {
212
- console.log("āŒ Test ERROR:", error);
213
- }
214
- }
215
- // ============================================================================
216
- // TEST 4: Connection Error (should be classified as connection)
217
- // ============================================================================
218
- async function testConnectionError() {
219
- console.log("\nšŸ“‹ TEST 4: Connection Error");
220
- console.log("-".repeat(80));
221
- const isolatedPool = new MultiWorkflowPool();
222
- // Add a client that definitely doesn't exist
223
- isolatedPool.addClient("http://this-server-does-not-exist-12345:8188", {
224
- workflowAffinity: [],
225
- priority: 1
226
- });
227
- try {
228
- console.log("Attempting to connect to non-existent server...");
229
- await isolatedPool.init();
230
- console.log("āŒ Test FAILED: Should have failed to connect");
231
- }
232
- catch (error) {
233
- console.log("āœ… Test PASSED: Connection failed as expected");
234
- console.log(`Error classification should be: connection`);
235
- console.log(`Actual error:`, error);
236
- }
237
- finally {
238
- await isolatedPool.shutdown();
239
- }
240
- }
241
- // ============================================================================
242
- // TEST 5: Missing LoRA Error (should be classified as workflow_incompatibility)
243
- // ============================================================================
244
- async function testMissingLoRA() {
245
- console.log("\nšŸ“‹ TEST 5: Missing LoRA Error");
246
- console.log("-".repeat(80));
247
- const workflow = new Workflow({
248
- "1": {
249
- "inputs": {
250
- "text": "beautiful landscape"
251
- },
252
- "class_type": "CLIPTextEncode",
253
- "_meta": {
254
- "title": "CLIP Text Encode"
255
- }
256
- },
257
- "2": {
258
- "inputs": {
259
- "ckpt_name": "novaAnimeXL_ilV125.safetensors" // Use a model that exists on the servers
260
- },
261
- "class_type": "CheckpointLoaderSimple",
262
- "_meta": {
263
- "title": "Load Checkpoint"
264
- }
265
- },
266
- "3": {
267
- "inputs": {
268
- "lora_name": "this_lora_does_not_exist_12345.safetensors",
269
- "strength_model": 1.0,
270
- "strength_clip": 1.0,
271
- "model": ["2", 0],
272
- "clip": ["2", 1]
273
- },
274
- "class_type": "LoraLoader",
275
- "_meta": {
276
- "title": "Load LoRA"
277
- }
278
- },
279
- "4": {
280
- "inputs": {
281
- "width": 512,
282
- "height": 512,
283
- "batch_size": 1
284
- },
285
- "class_type": "EmptyLatentImage",
286
- "_meta": {
287
- "title": "Empty Latent Image"
288
- }
289
- },
290
- "5": {
291
- "inputs": {
292
- "seed": 12345,
293
- "steps": 20,
294
- "cfg": 7.0,
295
- "sampler_name": "euler",
296
- "scheduler": "normal",
297
- "denoise": 1.0,
298
- "model": ["3", 0],
299
- "positive": ["1", 0],
300
- "negative": ["1", 0],
301
- "latent_image": ["4", 0]
302
- },
303
- "class_type": "KSampler",
304
- "_meta": {
305
- "title": "KSampler"
306
- }
307
- },
308
- "6": {
309
- "inputs": {
310
- "samples": ["5", 0],
311
- "vae": ["2", 2]
312
- },
313
- "class_type": "VAEDecode",
314
- "_meta": {
315
- "title": "VAE Decode"
316
- }
317
- },
318
- "7": {
319
- "inputs": {
320
- "filename_prefix": "ComfyUI",
321
- "images": ["6", 0]
322
- },
323
- "class_type": "SaveImage",
324
- "_meta": {
325
- "title": "Save Image"
326
- }
327
- }
328
- });
329
- try {
330
- const jobId = await pool.submitJob(workflow);
331
- console.log(`Submitted job: ${jobId}`);
332
- const result = await pool.waitForJobCompletion(jobId);
333
- if (result.status === "failed") {
334
- console.log("āœ… Test PASSED: Job failed as expected");
335
- console.log(`Error classification should be: workflow_incompatibility`);
336
- console.log(`Actual error:`, result.error);
337
- }
338
- else {
339
- console.log("āŒ Test FAILED: Job should have failed but didn't");
340
- }
341
- }
342
- catch (error) {
343
- console.log("āŒ Test ERROR:", error);
344
- }
345
- }
346
- // ============================================================================
347
- // Run all tests
348
- // ============================================================================
349
- async function runAllTests() {
350
- try {
351
- await testMissingModel();
352
- await new Promise(resolve => setTimeout(resolve, 2000));
353
- await testMissingCustomNode();
354
- await new Promise(resolve => setTimeout(resolve, 2000));
355
- await testInvalidInput();
356
- await new Promise(resolve => setTimeout(resolve, 2000));
357
- await testMissingLoRA();
358
- await new Promise(resolve => setTimeout(resolve, 2000));
359
- await testConnectionError();
360
- console.log("\n" + "=".repeat(80));
361
- console.log("ALL TESTS COMPLETED");
362
- console.log("=".repeat(80) + "\n");
363
- }
364
- catch (error) {
365
- console.error("Fatal error during tests:", error);
366
- }
367
- finally {
368
- await pool.shutdown();
369
- process.exit(0);
370
- }
371
- }
372
- // Run the tests
373
- runAllTests();
1
+ import { MultiWorkflowPool } from "src/multipool/multi-workflow-pool.js";
2
+ import { Workflow } from "src/multipool/workflow.js";
3
+ /**
4
+ * Error Classification Validation Tests
5
+ *
6
+ * This script validates the error classification logic by intentionally triggering
7
+ * different types of errors from real ComfyUI servers.
8
+ *
9
+ * Test Cases:
10
+ * 1. Missing Model Error (workflow_incompatibility)
11
+ * 2. Missing Custom Node Error (workflow_incompatibility)
12
+ * 3. Invalid Input Error (transient)
13
+ * 4. Connection Error (connection)
14
+ */
15
+ const pool = new MultiWorkflowPool();
16
+ // Add your real ComfyUI servers here
17
+ pool.addClient("http://server1:8188", {
18
+ workflowAffinity: [],
19
+ priority: 1
20
+ });
21
+ pool.addClient("http://server2:8188", {
22
+ workflowAffinity: [],
23
+ priority: 1
24
+ });
25
+ pool.addClient("http://server3:8188", {
26
+ workflowAffinity: [],
27
+ priority: 1
28
+ });
29
+ await pool.init();
30
+ console.log("\n" + "=".repeat(80));
31
+ console.log("ERROR CLASSIFICATION VALIDATION TESTS");
32
+ console.log("=".repeat(80) + "\n");
33
+ // ============================================================================
34
+ // TEST 1: Missing Model Error (should be classified as workflow_incompatibility)
35
+ // ============================================================================
36
+ async function testMissingModel() {
37
+ console.log("\nšŸ“‹ TEST 1: Missing Model Error");
38
+ console.log("-".repeat(80));
39
+ const workflow = new Workflow({
40
+ "1": {
41
+ "inputs": {
42
+ "text": "beautiful landscape"
43
+ },
44
+ "class_type": "CLIPTextEncode",
45
+ "_meta": {
46
+ "title": "CLIP Text Encode (Prompt)"
47
+ }
48
+ },
49
+ "2": {
50
+ "inputs": {
51
+ "ckpt_name": "this_model_definitely_does_not_exist_anywhere_12345.safetensors"
52
+ },
53
+ "class_type": "CheckpointLoaderSimple",
54
+ "_meta": {
55
+ "title": "Load Checkpoint"
56
+ }
57
+ },
58
+ "3": {
59
+ "inputs": {
60
+ "seed": 12345,
61
+ "steps": 20,
62
+ "cfg": 7.0,
63
+ "sampler_name": "euler",
64
+ "scheduler": "normal",
65
+ "denoise": 1.0,
66
+ "model": ["2", 0],
67
+ "positive": ["1", 0],
68
+ "negative": ["1", 0],
69
+ "latent_image": ["4", 0]
70
+ },
71
+ "class_type": "KSampler",
72
+ "_meta": {
73
+ "title": "KSampler"
74
+ }
75
+ },
76
+ "4": {
77
+ "inputs": {
78
+ "width": 512,
79
+ "height": 512,
80
+ "batch_size": 1
81
+ },
82
+ "class_type": "EmptyLatentImage",
83
+ "_meta": {
84
+ "title": "Empty Latent Image"
85
+ }
86
+ },
87
+ "5": {
88
+ "inputs": {
89
+ "samples": ["3", 0],
90
+ "vae": ["2", 2]
91
+ },
92
+ "class_type": "VAEDecode",
93
+ "_meta": {
94
+ "title": "VAE Decode"
95
+ }
96
+ },
97
+ "6": {
98
+ "inputs": {
99
+ "filename_prefix": "ComfyUI",
100
+ "images": ["5", 0]
101
+ },
102
+ "class_type": "SaveImage",
103
+ "_meta": {
104
+ "title": "Save Image"
105
+ }
106
+ }
107
+ });
108
+ try {
109
+ const jobId = await pool.submitJob(workflow);
110
+ console.log(`Submitted job: ${jobId}`);
111
+ const result = await pool.waitForJobCompletion(jobId);
112
+ if (result.status === "failed") {
113
+ console.log("āœ… Test PASSED: Job failed as expected");
114
+ console.log(`Error classification should be: workflow_incompatibility`);
115
+ console.log(`Actual error:`, result.error);
116
+ }
117
+ else {
118
+ console.log("āŒ Test FAILED: Job should have failed but didn't");
119
+ }
120
+ }
121
+ catch (error) {
122
+ console.log("āŒ Test ERROR:", error);
123
+ }
124
+ }
125
+ // ============================================================================
126
+ // TEST 2: Missing Custom Node Error (should be classified as workflow_incompatibility)
127
+ // ============================================================================
128
+ async function testMissingCustomNode() {
129
+ console.log("\nšŸ“‹ TEST 2: Missing Custom Node Error");
130
+ console.log("-".repeat(80));
131
+ const workflow = new Workflow({
132
+ "1": {
133
+ "inputs": {
134
+ "some_input": "test"
135
+ },
136
+ "class_type": "NonExistentCustomNode_XYZ_12345",
137
+ "_meta": {
138
+ "title": "This Node Does Not Exist"
139
+ }
140
+ },
141
+ "2": {
142
+ "inputs": {
143
+ "filename_prefix": "test",
144
+ "images": ["1", 0]
145
+ },
146
+ "class_type": "SaveImage",
147
+ "_meta": {
148
+ "title": "Save Image"
149
+ }
150
+ }
151
+ });
152
+ try {
153
+ const jobId = await pool.submitJob(workflow);
154
+ console.log(`Submitted job: ${jobId}`);
155
+ const result = await pool.waitForJobCompletion(jobId);
156
+ if (result.status === "failed") {
157
+ console.log("āœ… Test PASSED: Job failed as expected");
158
+ console.log(`Error classification should be: workflow_incompatibility`);
159
+ console.log(`Actual error:`, result.error);
160
+ }
161
+ else {
162
+ console.log("āŒ Test FAILED: Job should have failed but didn't");
163
+ }
164
+ }
165
+ catch (error) {
166
+ console.log("āŒ Test ERROR:", error);
167
+ }
168
+ }
169
+ // ============================================================================
170
+ // TEST 3: Invalid Input Error (should be classified as transient)
171
+ // ============================================================================
172
+ async function testInvalidInput() {
173
+ console.log("\nšŸ“‹ TEST 3: Invalid Input Error");
174
+ console.log("-".repeat(80));
175
+ const workflow = new Workflow({
176
+ "1": {
177
+ "inputs": {
178
+ "width": -999999, // Negative width should cause validation error
179
+ "height": -999999, // Negative height should cause validation error
180
+ "batch_size": 1
181
+ },
182
+ "class_type": "EmptyLatentImage",
183
+ "_meta": {
184
+ "title": "Empty Latent Image"
185
+ }
186
+ },
187
+ "2": {
188
+ "inputs": {
189
+ "filename_prefix": "test",
190
+ "images": ["1", 0]
191
+ },
192
+ "class_type": "SaveImage",
193
+ "_meta": {
194
+ "title": "Save Image"
195
+ }
196
+ }
197
+ });
198
+ try {
199
+ const jobId = await pool.submitJob(workflow);
200
+ console.log(`Submitted job: ${jobId}`);
201
+ const result = await pool.waitForJobCompletion(jobId);
202
+ if (result.status === "failed") {
203
+ console.log("āœ… Test PASSED: Job failed as expected");
204
+ console.log(`Error classification should be: transient`);
205
+ console.log(`Actual error:`, result.error);
206
+ }
207
+ else {
208
+ console.log("āŒ Test FAILED: Job should have failed but didn't");
209
+ }
210
+ }
211
+ catch (error) {
212
+ console.log("āŒ Test ERROR:", error);
213
+ }
214
+ }
215
+ // ============================================================================
216
+ // TEST 4: Connection Error (should be classified as connection)
217
+ // ============================================================================
218
+ async function testConnectionError() {
219
+ console.log("\nšŸ“‹ TEST 4: Connection Error");
220
+ console.log("-".repeat(80));
221
+ const isolatedPool = new MultiWorkflowPool();
222
+ // Add a client that definitely doesn't exist
223
+ isolatedPool.addClient("http://this-server-does-not-exist-12345:8188", {
224
+ workflowAffinity: [],
225
+ priority: 1
226
+ });
227
+ try {
228
+ console.log("Attempting to connect to non-existent server...");
229
+ await isolatedPool.init();
230
+ console.log("āŒ Test FAILED: Should have failed to connect");
231
+ }
232
+ catch (error) {
233
+ console.log("āœ… Test PASSED: Connection failed as expected");
234
+ console.log(`Error classification should be: connection`);
235
+ console.log(`Actual error:`, error);
236
+ }
237
+ finally {
238
+ await isolatedPool.shutdown();
239
+ }
240
+ }
241
+ // ============================================================================
242
+ // TEST 5: Missing LoRA Error (should be classified as workflow_incompatibility)
243
+ // ============================================================================
244
+ async function testMissingLoRA() {
245
+ console.log("\nšŸ“‹ TEST 5: Missing LoRA Error");
246
+ console.log("-".repeat(80));
247
+ const workflow = new Workflow({
248
+ "1": {
249
+ "inputs": {
250
+ "text": "beautiful landscape"
251
+ },
252
+ "class_type": "CLIPTextEncode",
253
+ "_meta": {
254
+ "title": "CLIP Text Encode"
255
+ }
256
+ },
257
+ "2": {
258
+ "inputs": {
259
+ "ckpt_name": "novaAnimeXL_ilV125.safetensors" // Use a model that exists on the servers
260
+ },
261
+ "class_type": "CheckpointLoaderSimple",
262
+ "_meta": {
263
+ "title": "Load Checkpoint"
264
+ }
265
+ },
266
+ "3": {
267
+ "inputs": {
268
+ "lora_name": "this_lora_does_not_exist_12345.safetensors",
269
+ "strength_model": 1.0,
270
+ "strength_clip": 1.0,
271
+ "model": ["2", 0],
272
+ "clip": ["2", 1]
273
+ },
274
+ "class_type": "LoraLoader",
275
+ "_meta": {
276
+ "title": "Load LoRA"
277
+ }
278
+ },
279
+ "4": {
280
+ "inputs": {
281
+ "width": 512,
282
+ "height": 512,
283
+ "batch_size": 1
284
+ },
285
+ "class_type": "EmptyLatentImage",
286
+ "_meta": {
287
+ "title": "Empty Latent Image"
288
+ }
289
+ },
290
+ "5": {
291
+ "inputs": {
292
+ "seed": 12345,
293
+ "steps": 20,
294
+ "cfg": 7.0,
295
+ "sampler_name": "euler",
296
+ "scheduler": "normal",
297
+ "denoise": 1.0,
298
+ "model": ["3", 0],
299
+ "positive": ["1", 0],
300
+ "negative": ["1", 0],
301
+ "latent_image": ["4", 0]
302
+ },
303
+ "class_type": "KSampler",
304
+ "_meta": {
305
+ "title": "KSampler"
306
+ }
307
+ },
308
+ "6": {
309
+ "inputs": {
310
+ "samples": ["5", 0],
311
+ "vae": ["2", 2]
312
+ },
313
+ "class_type": "VAEDecode",
314
+ "_meta": {
315
+ "title": "VAE Decode"
316
+ }
317
+ },
318
+ "7": {
319
+ "inputs": {
320
+ "filename_prefix": "ComfyUI",
321
+ "images": ["6", 0]
322
+ },
323
+ "class_type": "SaveImage",
324
+ "_meta": {
325
+ "title": "Save Image"
326
+ }
327
+ }
328
+ });
329
+ try {
330
+ const jobId = await pool.submitJob(workflow);
331
+ console.log(`Submitted job: ${jobId}`);
332
+ const result = await pool.waitForJobCompletion(jobId);
333
+ if (result.status === "failed") {
334
+ console.log("āœ… Test PASSED: Job failed as expected");
335
+ console.log(`Error classification should be: workflow_incompatibility`);
336
+ console.log(`Actual error:`, result.error);
337
+ }
338
+ else {
339
+ console.log("āŒ Test FAILED: Job should have failed but didn't");
340
+ }
341
+ }
342
+ catch (error) {
343
+ console.log("āŒ Test ERROR:", error);
344
+ }
345
+ }
346
+ // ============================================================================
347
+ // Run all tests
348
+ // ============================================================================
349
+ async function runAllTests() {
350
+ try {
351
+ await testMissingModel();
352
+ await new Promise(resolve => setTimeout(resolve, 2000));
353
+ await testMissingCustomNode();
354
+ await new Promise(resolve => setTimeout(resolve, 2000));
355
+ await testInvalidInput();
356
+ await new Promise(resolve => setTimeout(resolve, 2000));
357
+ await testMissingLoRA();
358
+ await new Promise(resolve => setTimeout(resolve, 2000));
359
+ await testConnectionError();
360
+ console.log("\n" + "=".repeat(80));
361
+ console.log("ALL TESTS COMPLETED");
362
+ console.log("=".repeat(80) + "\n");
363
+ }
364
+ catch (error) {
365
+ console.error("Fatal error during tests:", error);
366
+ }
367
+ finally {
368
+ await pool.shutdown();
369
+ process.exit(0);
370
+ }
371
+ }
372
+ // Run the tests
373
+ runAllTests();
374
374
  //# sourceMappingURL=error-classification-tests.js.map