comfyui-mcp 0.1.0

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 (90) hide show
  1. package/.mcp.json +11 -0
  2. package/dist/comfyui/client.d.ts +16 -0
  3. package/dist/comfyui/client.d.ts.map +1 -0
  4. package/dist/comfyui/client.js +75 -0
  5. package/dist/comfyui/client.js.map +1 -0
  6. package/dist/comfyui/events.d.ts +9 -0
  7. package/dist/comfyui/events.d.ts.map +1 -0
  8. package/dist/comfyui/events.js +40 -0
  9. package/dist/comfyui/events.js.map +1 -0
  10. package/dist/comfyui/types.d.ts +66 -0
  11. package/dist/comfyui/types.d.ts.map +1 -0
  12. package/dist/comfyui/types.js +3 -0
  13. package/dist/comfyui/types.js.map +1 -0
  14. package/dist/config.d.ts +28 -0
  15. package/dist/config.d.ts.map +1 -0
  16. package/dist/config.js +93 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +22 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/services/mermaid-converter.d.ts +8 -0
  23. package/dist/services/mermaid-converter.d.ts.map +1 -0
  24. package/dist/services/mermaid-converter.js +235 -0
  25. package/dist/services/mermaid-converter.js.map +1 -0
  26. package/dist/services/mermaid-parser.d.ts +31 -0
  27. package/dist/services/mermaid-parser.d.ts.map +1 -0
  28. package/dist/services/mermaid-parser.js +464 -0
  29. package/dist/services/mermaid-parser.js.map +1 -0
  30. package/dist/services/model-resolver.d.ts +25 -0
  31. package/dist/services/model-resolver.d.ts.map +1 -0
  32. package/dist/services/model-resolver.js +123 -0
  33. package/dist/services/model-resolver.js.map +1 -0
  34. package/dist/services/registry-client.d.ts +28 -0
  35. package/dist/services/registry-client.d.ts.map +1 -0
  36. package/dist/services/registry-client.js +32 -0
  37. package/dist/services/registry-client.js.map +1 -0
  38. package/dist/services/skill-generator.d.ts +33 -0
  39. package/dist/services/skill-generator.d.ts.map +1 -0
  40. package/dist/services/skill-generator.js +438 -0
  41. package/dist/services/skill-generator.js.map +1 -0
  42. package/dist/services/workflow-composer.d.ts +43 -0
  43. package/dist/services/workflow-composer.d.ts.map +1 -0
  44. package/dist/services/workflow-composer.js +333 -0
  45. package/dist/services/workflow-composer.js.map +1 -0
  46. package/dist/services/workflow-executor.d.ts +15 -0
  47. package/dist/services/workflow-executor.d.ts.map +1 -0
  48. package/dist/services/workflow-executor.js +63 -0
  49. package/dist/services/workflow-executor.js.map +1 -0
  50. package/dist/tools/index.d.ts +3 -0
  51. package/dist/tools/index.d.ts.map +1 -0
  52. package/dist/tools/index.js +15 -0
  53. package/dist/tools/index.js.map +1 -0
  54. package/dist/tools/model-management.d.ts +3 -0
  55. package/dist/tools/model-management.d.ts.map +1 -0
  56. package/dist/tools/model-management.js +97 -0
  57. package/dist/tools/model-management.js.map +1 -0
  58. package/dist/tools/registry-search.d.ts +3 -0
  59. package/dist/tools/registry-search.d.ts.map +1 -0
  60. package/dist/tools/registry-search.js +70 -0
  61. package/dist/tools/registry-search.js.map +1 -0
  62. package/dist/tools/skill-generator.d.ts +3 -0
  63. package/dist/tools/skill-generator.d.ts.map +1 -0
  64. package/dist/tools/skill-generator.js +42 -0
  65. package/dist/tools/skill-generator.js.map +1 -0
  66. package/dist/tools/workflow-compose.d.ts +3 -0
  67. package/dist/tools/workflow-compose.d.ts.map +1 -0
  68. package/dist/tools/workflow-compose.js +180 -0
  69. package/dist/tools/workflow-compose.js.map +1 -0
  70. package/dist/tools/workflow-execute.d.ts +3 -0
  71. package/dist/tools/workflow-execute.d.ts.map +1 -0
  72. package/dist/tools/workflow-execute.js +115 -0
  73. package/dist/tools/workflow-execute.js.map +1 -0
  74. package/dist/tools/workflow-visualize.d.ts +3 -0
  75. package/dist/tools/workflow-visualize.d.ts.map +1 -0
  76. package/dist/tools/workflow-visualize.js +111 -0
  77. package/dist/tools/workflow-visualize.js.map +1 -0
  78. package/dist/utils/errors.d.ts +24 -0
  79. package/dist/utils/errors.d.ts.map +1 -0
  80. package/dist/utils/errors.js +65 -0
  81. package/dist/utils/errors.js.map +1 -0
  82. package/dist/utils/image.d.ts +4 -0
  83. package/dist/utils/image.d.ts.map +1 -0
  84. package/dist/utils/image.js +10 -0
  85. package/dist/utils/image.js.map +1 -0
  86. package/dist/utils/logger.d.ts +7 -0
  87. package/dist/utils/logger.d.ts.map +1 -0
  88. package/dist/utils/logger.js +22 -0
  89. package/dist/utils/logger.js.map +1 -0
  90. package/package.json +34 -0
@@ -0,0 +1,464 @@
1
+ import { ValidationError } from "../utils/errors.js";
2
+ import { logger } from "../utils/logger.js";
3
+ /**
4
+ * Parse a mermaid flowchart string into structured nodes and edges.
5
+ */
6
+ export function parseMermaid(mermaidText) {
7
+ // Strip code fence if present
8
+ let text = mermaidText.trim();
9
+ if (text.startsWith("```")) {
10
+ text = text.replace(/^```(?:mermaid)?\s*\n?/, "").replace(/\n?```\s*$/, "");
11
+ }
12
+ const lines = text.split("\n").map((l) => l.trim());
13
+ const nodes = new Map();
14
+ const edges = [];
15
+ let direction = "LR";
16
+ for (const line of lines) {
17
+ // Parse direction from flowchart declaration
18
+ const dirMatch = line.match(/^flowchart\s+(LR|TB|TD|RL)$/);
19
+ if (dirMatch) {
20
+ direction = dirMatch[1] === "TD" ? "TB" : dirMatch[1];
21
+ continue;
22
+ }
23
+ // Skip subgraph/end/style/linkStyle lines
24
+ if (line.startsWith("subgraph ") ||
25
+ line === "end" ||
26
+ line.startsWith("style ") ||
27
+ line.startsWith("linkStyle ") ||
28
+ line === "") {
29
+ continue;
30
+ }
31
+ // Try to parse as edge: sourceId -->|TYPE| targetId OR sourceId --> targetId
32
+ const edgeMatch = line.match(/^(\S+)\s+--+>(?:\|([^|]*)\|)?\s*(\S+)$/);
33
+ if (edgeMatch) {
34
+ edges.push({
35
+ sourceId: edgeMatch[1],
36
+ targetId: edgeMatch[3],
37
+ dataType: edgeMatch[2] || undefined,
38
+ });
39
+ continue;
40
+ }
41
+ // Try to parse as node definition with various shapes
42
+ const nodeResult = parseNodeLine(line);
43
+ if (nodeResult) {
44
+ nodes.set(nodeResult.id, nodeResult);
45
+ }
46
+ }
47
+ if (nodes.size === 0) {
48
+ throw new ValidationError("Could not parse any nodes from mermaid text. Expected format: flowchart LR/TB with node definitions.");
49
+ }
50
+ return { nodes, edges, direction };
51
+ }
52
+ /**
53
+ * Parse a single node definition line.
54
+ * Handles all shape variants:
55
+ * id["label"] — rectangle (loading, utility)
56
+ * id(["label"]) — stadium (conditioning)
57
+ * id{{"label"}} — hexagon (sampling)
58
+ * id("label") — rounded (image)
59
+ * id((("label"))) — triple circle (output)
60
+ * id(("label")) — double circle
61
+ */
62
+ function parseNodeLine(line) {
63
+ // Match: id followed by shape-wrapped label
64
+ // The id is one or more non-whitespace chars at the start (before the shape opener)
65
+ const patterns = [
66
+ // Triple circle: id((("label")))
67
+ /^(\S+?)\(\(\("(.+?)"\)\)\)$/,
68
+ // Double circle: id(("label"))
69
+ /^(\S+?)\(\("(.+?)"\)\)$/,
70
+ // Hexagon: id{{"label"}}
71
+ /^(\S+?)\{\{"(.+?)"\}\}$/,
72
+ // Stadium: id(["label"])
73
+ /^(\S+?)\(\["(.+?)"\]\)$/,
74
+ // Rounded: id("label")
75
+ /^(\S+?)\("(.+?)"\)$/,
76
+ // Rectangle: id["label"]
77
+ /^(\S+?)\["(.+?)"\]$/,
78
+ ];
79
+ for (const pattern of patterns) {
80
+ const match = line.match(pattern);
81
+ if (match) {
82
+ const id = match[1];
83
+ const rawLabel = match[2];
84
+ return parseLabel(id, rawLabel);
85
+ }
86
+ }
87
+ return null;
88
+ }
89
+ /**
90
+ * Parse the inner label text.
91
+ * Format: "ClassName\nkey:value key2:value2"
92
+ * or: "Title\nkey:value key2:value2"
93
+ */
94
+ function parseLabel(id, rawLabel) {
95
+ // Unescape mermaid HTML entities
96
+ const label = rawLabel.replace(/#quot;/g, '"');
97
+ // Split on literal \n (the escaped newline in mermaid syntax)
98
+ const parts = label.split("\\n");
99
+ const title = parts[0].trim();
100
+ const values = {};
101
+ if (parts.length > 1) {
102
+ // The rest is space-separated key:value pairs
103
+ const valuesStr = parts.slice(1).join(" ");
104
+ // Parse key:value pairs. Values can contain colons (filenames like model.safetensors),
105
+ // so we match key up to first colon, then value up to next key or end.
106
+ // Pattern: word chars + colon + value (up to next space-followed-by-word-colon, or end)
107
+ const kvRegex = /(\w+):(.+?)(?=\s+\w+:|$)/g;
108
+ let kvMatch;
109
+ while ((kvMatch = kvRegex.exec(valuesStr)) !== null) {
110
+ values[kvMatch[1]] = kvMatch[2].trim();
111
+ }
112
+ }
113
+ return { id, label: title, values };
114
+ }
115
+ /**
116
+ * Resolve a parsed mermaid graph into a valid ComfyUI workflow JSON
117
+ * using node definitions from /object_info.
118
+ */
119
+ export function resolveWorkflow(parsed, objectInfo) {
120
+ const workflow = {};
121
+ const warnings = [];
122
+ // Build lookup: display_name → class_type
123
+ const displayNameMap = new Map();
124
+ for (const [className, def] of Object.entries(objectInfo)) {
125
+ if (def.display_name) {
126
+ displayNameMap.set(def.display_name.toLowerCase(), className);
127
+ }
128
+ // Also map the class name itself (case-insensitive)
129
+ displayNameMap.set(className.toLowerCase(), className);
130
+ }
131
+ // Phase 1: Resolve each node's class_type
132
+ const nodeClassTypes = new Map();
133
+ for (const [id, node] of parsed.nodes) {
134
+ const resolved = resolveClassType(node.label, objectInfo, displayNameMap);
135
+ if (resolved) {
136
+ nodeClassTypes.set(id, resolved);
137
+ }
138
+ else {
139
+ // Try inferring from connection data type signature
140
+ const inferred = inferClassTypeFromConnections(id, parsed.edges, objectInfo);
141
+ if (inferred) {
142
+ nodeClassTypes.set(id, inferred);
143
+ logger.info(`Node ${id}: Inferred class_type "${inferred}" from connection signature for label "${node.label}"`);
144
+ }
145
+ else {
146
+ warnings.push(`Node ${id}: Could not resolve "${node.label}" to a known ComfyUI node type. Using label as class_type.`);
147
+ nodeClassTypes.set(id, node.label);
148
+ }
149
+ }
150
+ }
151
+ // Phase 2: Create workflow nodes with empty inputs
152
+ for (const [id, node] of parsed.nodes) {
153
+ const classType = nodeClassTypes.get(id);
154
+ workflow[id] = {
155
+ class_type: classType,
156
+ inputs: {},
157
+ };
158
+ // If the label differs from class_type, preserve it as _meta.title
159
+ if (node.label !== classType) {
160
+ workflow[id]._meta = { title: node.label };
161
+ }
162
+ }
163
+ // Phase 3: Wire connections using edge data types + object_info
164
+ for (const edge of parsed.edges) {
165
+ const sourceClassType = nodeClassTypes.get(edge.sourceId);
166
+ const targetClassType = nodeClassTypes.get(edge.targetId);
167
+ if (!sourceClassType || !targetClassType) {
168
+ warnings.push(`Edge ${edge.sourceId} → ${edge.targetId}: source or target node not found, skipping.`);
169
+ continue;
170
+ }
171
+ const sourceDef = objectInfo[sourceClassType];
172
+ const targetDef = objectInfo[targetClassType];
173
+ if (!sourceDef || !targetDef) {
174
+ warnings.push(`Edge ${edge.sourceId} → ${edge.targetId}: missing object_info for ${!sourceDef ? sourceClassType : targetClassType}. Using best guess.`);
175
+ // Best effort: put connection as first matching input
176
+ if (edge.dataType) {
177
+ const inputName = guessInputNameByType(edge.dataType, targetClassType);
178
+ if (inputName) {
179
+ workflow[edge.targetId].inputs[inputName] = [edge.sourceId, 0];
180
+ }
181
+ }
182
+ continue;
183
+ }
184
+ // Find the output index on the source that produces this data type
185
+ let outputIndex = 0;
186
+ if (edge.dataType && sourceDef.output) {
187
+ const idx = sourceDef.output.indexOf(edge.dataType);
188
+ if (idx >= 0) {
189
+ outputIndex = idx;
190
+ }
191
+ else {
192
+ warnings.push(`Edge ${edge.sourceId} → ${edge.targetId}: data type "${edge.dataType}" not found in ${sourceClassType} outputs [${sourceDef.output.join(", ")}]. Using index 0.`);
193
+ }
194
+ }
195
+ // Find the input name on the target that accepts this data type.
196
+ // Use the source node's title as a hint for disambiguation
197
+ // (e.g., "Positive Prompt" → positive, "Negative Prompt" → negative).
198
+ const sourceTitle = parsed.nodes.get(edge.sourceId)?.label ?? "";
199
+ const inputName = findInputForType(targetDef, edge.dataType, workflow[edge.targetId].inputs, sourceTitle);
200
+ if (inputName) {
201
+ workflow[edge.targetId].inputs[inputName] = [edge.sourceId, outputIndex];
202
+ }
203
+ else {
204
+ warnings.push(`Edge ${edge.sourceId} → ${edge.targetId}: could not find input on ${targetClassType} that accepts "${edge.dataType}".`);
205
+ }
206
+ }
207
+ // Phase 4: Fill widget values from parsed labels
208
+ for (const [id, node] of parsed.nodes) {
209
+ const classType = nodeClassTypes.get(id);
210
+ const def = objectInfo[classType];
211
+ if (!def)
212
+ continue;
213
+ for (const [key, rawValue] of Object.entries(node.values)) {
214
+ // Don't overwrite connections
215
+ if (isConnectionValue(workflow[id].inputs[key]))
216
+ continue;
217
+ // Coerce value to the correct type based on objectInfo
218
+ const coerced = coerceValue(key, rawValue, def);
219
+ if (coerced !== undefined) {
220
+ workflow[id].inputs[key] = coerced;
221
+ }
222
+ else {
223
+ // Fall back to string
224
+ workflow[id].inputs[key] = rawValue;
225
+ }
226
+ }
227
+ }
228
+ // Phase 5: Fill remaining required inputs with defaults from objectInfo
229
+ for (const [id] of parsed.nodes) {
230
+ const classType = nodeClassTypes.get(id);
231
+ const def = objectInfo[classType];
232
+ if (!def)
233
+ continue;
234
+ fillDefaults(workflow[id], def, warnings, id);
235
+ }
236
+ return { workflow, warnings };
237
+ }
238
+ /**
239
+ * Infer class_type by matching a node's connection signature against all known node types.
240
+ * E.g., a node that receives CLIP and outputs CONDITIONING is very likely CLIPTextEncode.
241
+ */
242
+ function inferClassTypeFromConnections(nodeId, edges, objectInfo) {
243
+ // Collect incoming and outgoing data types for this node
244
+ const incomingTypes = new Set();
245
+ const outgoingTypes = new Set();
246
+ for (const edge of edges) {
247
+ if (edge.targetId === nodeId && edge.dataType) {
248
+ incomingTypes.add(edge.dataType);
249
+ }
250
+ if (edge.sourceId === nodeId && edge.dataType) {
251
+ outgoingTypes.add(edge.dataType);
252
+ }
253
+ }
254
+ if (incomingTypes.size === 0 && outgoingTypes.size === 0)
255
+ return null;
256
+ // Score each node type by how well it matches the signature
257
+ let bestMatch = null;
258
+ let bestScore = 0;
259
+ for (const [className, def] of Object.entries(objectInfo)) {
260
+ let score = 0;
261
+ // Check outgoing types match outputs
262
+ if (outgoingTypes.size > 0) {
263
+ const outputSet = new Set(def.output);
264
+ for (const t of outgoingTypes) {
265
+ if (outputSet.has(t))
266
+ score += 2;
267
+ }
268
+ }
269
+ // Check incoming types match inputs
270
+ if (incomingTypes.size > 0) {
271
+ const allInputs = {
272
+ ...def.input.required,
273
+ ...def.input.optional,
274
+ };
275
+ const inputTypes = new Set(Object.values(allInputs).map((spec) => typeof spec[0] === "string" ? spec[0] : ""));
276
+ for (const t of incomingTypes) {
277
+ if (inputTypes.has(t))
278
+ score += 1;
279
+ }
280
+ }
281
+ if (score > bestScore) {
282
+ bestScore = score;
283
+ bestMatch = className;
284
+ }
285
+ }
286
+ // Require a minimum score to avoid false matches
287
+ return bestScore >= 2 ? bestMatch : null;
288
+ }
289
+ /**
290
+ * Resolve a label to a known class_type.
291
+ */
292
+ function resolveClassType(label, objectInfo, displayNameMap) {
293
+ // Direct match against class names
294
+ if (objectInfo[label])
295
+ return label;
296
+ // Case-insensitive match
297
+ const lower = label.toLowerCase();
298
+ const fromDisplay = displayNameMap.get(lower);
299
+ if (fromDisplay)
300
+ return fromDisplay;
301
+ // Fuzzy: try removing spaces (e.g., "Checkpoint Loader Simple" → "CheckpointLoaderSimple")
302
+ const noSpaces = label.replace(/\s+/g, "");
303
+ if (objectInfo[noSpaces])
304
+ return noSpaces;
305
+ // Try display name without spaces
306
+ const fromDisplayNoSpaces = displayNameMap.get(noSpaces.toLowerCase());
307
+ if (fromDisplayNoSpaces)
308
+ return fromDisplayNoSpaces;
309
+ return null;
310
+ }
311
+ /**
312
+ * Find an input on the target node that accepts the given data type.
313
+ * Avoids assigning to an input that already has a connection.
314
+ * Uses sourceTitle as a hint when multiple inputs accept the same type
315
+ * (e.g., KSampler has both "positive" and "negative" CONDITIONING inputs).
316
+ */
317
+ function findInputForType(targetDef, dataType, currentInputs, sourceTitle) {
318
+ if (!dataType)
319
+ return null;
320
+ const allInputs = {
321
+ ...targetDef.input.required,
322
+ ...targetDef.input.optional,
323
+ };
324
+ // Collect all matching, unwired inputs
325
+ const candidates = [];
326
+ for (const [inputName, spec] of Object.entries(allInputs)) {
327
+ if (isConnectionValue(currentInputs[inputName]))
328
+ continue;
329
+ const acceptedType = spec[0];
330
+ const matches = (typeof acceptedType === "string" && acceptedType === dataType) ||
331
+ (Array.isArray(acceptedType) && acceptedType.includes(dataType));
332
+ if (matches) {
333
+ candidates.push(inputName);
334
+ }
335
+ }
336
+ if (candidates.length === 0)
337
+ return null;
338
+ if (candidates.length === 1)
339
+ return candidates[0];
340
+ // Multiple candidates — use sourceTitle to pick the best match.
341
+ // E.g., title "Positive Prompt" should match input named "positive",
342
+ // and "Negative Prompt" should match "negative".
343
+ if (sourceTitle) {
344
+ const titleLower = sourceTitle.toLowerCase();
345
+ for (const inputName of candidates) {
346
+ if (titleLower.includes(inputName.toLowerCase())) {
347
+ return inputName;
348
+ }
349
+ }
350
+ }
351
+ // Fall back to first available
352
+ return candidates[0];
353
+ }
354
+ /**
355
+ * Fallback: guess input name from data type for common patterns.
356
+ */
357
+ function guessInputNameByType(dataType, _targetClassType) {
358
+ const typeToInput = {
359
+ MODEL: "model",
360
+ CLIP: "clip",
361
+ VAE: "vae",
362
+ CONDITIONING: "positive", // ambiguous but common
363
+ LATENT: "latent_image",
364
+ IMAGE: "images",
365
+ MASK: "mask",
366
+ CONTROL_NET: "control_net",
367
+ UPSCALE_MODEL: "upscale_model",
368
+ };
369
+ return typeToInput[dataType] ?? null;
370
+ }
371
+ /**
372
+ * Coerce a string value to the expected type based on objectInfo.
373
+ */
374
+ function coerceValue(key, rawValue, def) {
375
+ const spec = findInputSpec(key, def);
376
+ if (!spec)
377
+ return undefined;
378
+ const [typeOrEnum, options] = spec;
379
+ // Enum type (array of allowed string values)
380
+ if (Array.isArray(typeOrEnum)) {
381
+ // Return the raw value if it's in the enum, otherwise closest match
382
+ if (typeOrEnum.includes(rawValue))
383
+ return rawValue;
384
+ // Try case-insensitive
385
+ const found = typeOrEnum.find((v) => typeof v === "string" && v.toLowerCase() === rawValue.toLowerCase());
386
+ return found ?? rawValue;
387
+ }
388
+ switch (typeOrEnum) {
389
+ case "INT": {
390
+ const n = Number(rawValue);
391
+ return Number.isFinite(n) ? Math.round(n) : undefined;
392
+ }
393
+ case "FLOAT": {
394
+ const n = Number(rawValue);
395
+ return Number.isFinite(n) ? n : undefined;
396
+ }
397
+ case "BOOLEAN":
398
+ return rawValue === "true" || rawValue === "1";
399
+ case "STRING":
400
+ return rawValue;
401
+ default:
402
+ // Unknown type — might be a connection type like MODEL, CLIP
403
+ // Don't set scalar values for connection types
404
+ return undefined;
405
+ }
406
+ }
407
+ /**
408
+ * Find the input spec for a given key in a node definition.
409
+ */
410
+ function findInputSpec(key, def) {
411
+ if (def.input.required?.[key])
412
+ return def.input.required[key];
413
+ if (def.input.optional?.[key])
414
+ return def.input.optional[key];
415
+ return null;
416
+ }
417
+ /**
418
+ * Fill required inputs that weren't set by connections or parsed values.
419
+ */
420
+ function fillDefaults(node, def, warnings, nodeId) {
421
+ const required = def.input.required ?? {};
422
+ for (const [inputName, spec] of Object.entries(required)) {
423
+ // Skip if already set
424
+ if (node.inputs[inputName] !== undefined)
425
+ continue;
426
+ const [typeOrEnum, options] = spec;
427
+ // Connection types (MODEL, CLIP, etc.) — can't fill with defaults, skip
428
+ if (typeof typeOrEnum === "string" &&
429
+ typeOrEnum === typeOrEnum.toUpperCase() &&
430
+ typeOrEnum.length > 1 &&
431
+ !["INT", "FLOAT", "STRING", "BOOLEAN"].includes(typeOrEnum)) {
432
+ continue;
433
+ }
434
+ // Enum: use first option as default
435
+ if (Array.isArray(typeOrEnum) && typeOrEnum.length > 0) {
436
+ node.inputs[inputName] = typeOrEnum[0];
437
+ continue;
438
+ }
439
+ // Use explicit default if available
440
+ if (options && "default" in options) {
441
+ node.inputs[inputName] = options.default;
442
+ continue;
443
+ }
444
+ // No default available
445
+ logger.debug(`Node ${nodeId} (${node.class_type}): required input "${inputName}" has no value or default`);
446
+ }
447
+ // Also fill optional inputs that have defaults (for completeness)
448
+ const optional = def.input.optional ?? {};
449
+ for (const [inputName, spec] of Object.entries(optional)) {
450
+ if (node.inputs[inputName] !== undefined)
451
+ continue;
452
+ const [, options] = spec;
453
+ if (options && "default" in options) {
454
+ node.inputs[inputName] = options.default;
455
+ }
456
+ }
457
+ }
458
+ function isConnectionValue(value) {
459
+ return (Array.isArray(value) &&
460
+ value.length === 2 &&
461
+ typeof value[0] === "string" &&
462
+ typeof value[1] === "number");
463
+ }
464
+ //# sourceMappingURL=mermaid-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mermaid-parser.js","sourceRoot":"","sources":["../../src/services/mermaid-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ export declare const MODEL_SUBDIRS: readonly ["checkpoints", "loras", "vae", "upscale_models", "controlnet", "embeddings", "clip", "diffusers", "gligen", "hypernetworks", "photomaker", "style_models", "unet"];
2
+ export type ModelType = (typeof MODEL_SUBDIRS)[number];
3
+ export interface HFModelResult {
4
+ id: string;
5
+ modelId: string;
6
+ author: string;
7
+ tags: string[];
8
+ downloads: number;
9
+ likes: number;
10
+ lastModified: string;
11
+ }
12
+ export interface LocalModel {
13
+ name: string;
14
+ path: string;
15
+ size: number;
16
+ modified: string;
17
+ type: string;
18
+ }
19
+ export declare function searchHuggingFaceModels(query: string, options?: {
20
+ filter?: string;
21
+ limit?: number;
22
+ }): Promise<HFModelResult[]>;
23
+ export declare function listLocalModels(modelType?: string): Promise<LocalModel[]>;
24
+ export declare function downloadModel(url: string, targetSubfolder: string, filename?: string): Promise<string>;
25
+ //# sourceMappingURL=model-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-resolver.d.ts","sourceRoot":"","sources":["../../src/services/model-resolver.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,aAAa,8KAchB,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AASD,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAChD,OAAO,CAAC,aAAa,EAAE,CAAC,CAoC1B;AAED,wBAAsB,eAAe,CACnC,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,UAAU,EAAE,CAAC,CAqCvB;AAED,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,MAAM,EACvB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CAqCjB"}
@@ -0,0 +1,123 @@
1
+ import { readdir, stat, mkdir } from "node:fs/promises";
2
+ import { createWriteStream } from "node:fs";
3
+ import { pipeline } from "node:stream/promises";
4
+ import { Readable } from "node:stream";
5
+ import { join, basename } from "node:path";
6
+ import { config } from "../config.js";
7
+ import { ModelError } from "../utils/errors.js";
8
+ import { logger } from "../utils/logger.js";
9
+ export const MODEL_SUBDIRS = [
10
+ "checkpoints",
11
+ "loras",
12
+ "vae",
13
+ "upscale_models",
14
+ "controlnet",
15
+ "embeddings",
16
+ "clip",
17
+ "diffusers",
18
+ "gligen",
19
+ "hypernetworks",
20
+ "photomaker",
21
+ "style_models",
22
+ "unet",
23
+ ];
24
+ function getModelsRoot() {
25
+ if (!config.comfyuiPath) {
26
+ throw new ModelError("COMFYUI_PATH is not configured. Set the COMFYUI_PATH environment variable.");
27
+ }
28
+ return join(config.comfyuiPath, "models");
29
+ }
30
+ export async function searchHuggingFaceModels(query, options = {}) {
31
+ const { filter, limit = 10 } = options;
32
+ const params = new URLSearchParams({
33
+ search: query,
34
+ limit: String(limit),
35
+ });
36
+ if (filter)
37
+ params.set("filter", filter);
38
+ const headers = {};
39
+ if (config.huggingfaceToken) {
40
+ headers["Authorization"] = `Bearer ${config.huggingfaceToken}`;
41
+ }
42
+ const url = `https://huggingface.co/api/models?${params}`;
43
+ logger.debug("HuggingFace API request", { url });
44
+ const res = await fetch(url, { headers });
45
+ if (!res.ok) {
46
+ const body = await res.text().catch(() => "");
47
+ throw new ModelError(`HuggingFace API ${res.status}: ${res.statusText}`, { url, status: res.status, body });
48
+ }
49
+ const data = (await res.json());
50
+ return data.map((m) => ({
51
+ id: String(m.id ?? m._id ?? ""),
52
+ modelId: String(m.modelId ?? m.id ?? ""),
53
+ author: String(m.author ?? ""),
54
+ tags: Array.isArray(m.tags) ? m.tags.map(String) : [],
55
+ downloads: Number(m.downloads ?? 0),
56
+ likes: Number(m.likes ?? 0),
57
+ lastModified: String(m.lastModified ?? ""),
58
+ }));
59
+ }
60
+ export async function listLocalModels(modelType) {
61
+ const modelsRoot = getModelsRoot();
62
+ const dirsToScan = modelType
63
+ ? [modelType]
64
+ : [...MODEL_SUBDIRS];
65
+ const results = [];
66
+ for (const dir of dirsToScan) {
67
+ const dirPath = join(modelsRoot, dir);
68
+ let entries;
69
+ try {
70
+ entries = await readdir(dirPath);
71
+ }
72
+ catch {
73
+ // Directory doesn't exist -- skip silently
74
+ continue;
75
+ }
76
+ for (const entry of entries) {
77
+ const filePath = join(dirPath, entry);
78
+ try {
79
+ const info = await stat(filePath);
80
+ if (!info.isFile())
81
+ continue;
82
+ results.push({
83
+ name: entry,
84
+ path: filePath,
85
+ size: info.size,
86
+ modified: info.mtime.toISOString(),
87
+ type: dir,
88
+ });
89
+ }
90
+ catch {
91
+ // Skip files we can't stat
92
+ }
93
+ }
94
+ }
95
+ return results;
96
+ }
97
+ export async function downloadModel(url, targetSubfolder, filename) {
98
+ const modelsRoot = getModelsRoot();
99
+ const targetDir = join(modelsRoot, targetSubfolder);
100
+ // Ensure target directory exists
101
+ await mkdir(targetDir, { recursive: true });
102
+ const resolvedFilename = filename ?? (basename(new URL(url).pathname) || "model.safetensors");
103
+ const targetPath = join(targetDir, resolvedFilename);
104
+ logger.info(`Downloading model to ${targetPath}`, { url });
105
+ const headers = {};
106
+ if (config.huggingfaceToken && url.includes("huggingface.co")) {
107
+ headers["Authorization"] = `Bearer ${config.huggingfaceToken}`;
108
+ }
109
+ const res = await fetch(url, { headers });
110
+ if (!res.ok) {
111
+ throw new ModelError(`Download failed: ${res.status} ${res.statusText}`, { url, status: res.status });
112
+ }
113
+ if (!res.body) {
114
+ throw new ModelError("Download response has no body", { url });
115
+ }
116
+ const nodeStream = Readable.fromWeb(res.body);
117
+ const fileStream = createWriteStream(targetPath);
118
+ await pipeline(nodeStream, fileStream);
119
+ const info = await stat(targetPath);
120
+ logger.info(`Download complete: ${resolvedFilename} (${(info.size / 1024 / 1024).toFixed(1)} MB)`);
121
+ return targetPath;
122
+ }
123
+ //# sourceMappingURL=model-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-resolver.js","sourceRoot":"","sources":["../../src/services/model-resolver.ts"],"names":[],"mappings":"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"}