Merge branch 'feat/compatibility-analyzer' into main

This commit is contained in:
Ethanfel
2026-03-08 01:53:17 +01:00
2 changed files with 1191 additions and 218 deletions
+105
View File
@@ -0,0 +1,105 @@
import { app } from "/scripts/app.js";
function findWidget(node, name) {
return node.widgets ? node.widgets.find((w) => w.name === name) : null;
}
app.registerExtension({
name: "LoRAOptimizer.CompatibilityAnalyzer",
nodeCreated(node) {
if (node.comfyClass !== "LoRACompatibilityAnalyzer") return;
if (!node.properties) node.properties = {};
if (!node.properties.createdGroupIds) node.properties.createdGroupIds = [];
// Clean up child stack nodes when analyzer is deleted
const origOnRemoved = node.onRemoved;
node.onRemoved = function () {
const tracked = this.properties?.createdGroupIds || [];
for (const id of tracked) {
if (id != null) {
const child = app.graph.getNodeById(id);
if (child && child.comfyClass === "LoRAStackDynamic") {
app.graph.remove(child);
}
}
}
if (origOnRemoved) origOnRemoved.call(this);
};
const origOnExecuted = node.onExecuted;
node.onExecuted = function (message) {
if (origOnExecuted) origOnExecuted.call(this, message);
const groups = message?.groups;
if (!groups) return;
const tracked = node.properties.createdGroupIds || [];
const newTracked = [];
// Update or create nodes for each group
for (let i = 0; i < groups.length; i++) {
const group = groups[i];
let stackNode = null;
// Try to reuse existing tracked node
if (i < tracked.length && tracked[i] != null) {
stackNode = app.graph.getNodeById(tracked[i]);
}
if (stackNode && stackNode.comfyClass === "LoRAStackDynamic") {
// Update existing node
populateStackNode(stackNode, group, i);
newTracked.push(stackNode.id);
} else {
// Create new node
const created = LiteGraph.createNode("LoRAStackDynamic");
if (!created) {
console.warn("[CompatibilityAnalyzer] LoRAStackDynamic node type not found");
continue;
}
app.graph.add(created);
created.pos = [
node.pos[0] + node.size[0] + 50,
node.pos[1] + i * 250,
];
created.title = `Group ${i + 1} (Analyzer)`;
// Delay population to let widgets initialize (must exceed
// the 100ms initial-visibility timeout in lora_stack_dynamic.js)
setTimeout(() => populateStackNode(created, group, i), 200);
newTracked.push(created.id);
}
}
// Remove orphaned nodes (groups shrank)
for (let i = groups.length; i < tracked.length; i++) {
if (tracked[i] != null) {
const orphan = app.graph.getNodeById(tracked[i]);
if (orphan && orphan.comfyClass === "LoRAStackDynamic") {
app.graph.remove(orphan);
}
}
}
node.properties.createdGroupIds = newTracked;
app.canvas?.setDirty?.(true, true);
};
},
});
function populateStackNode(stackNode, group, groupIndex) {
const modeWidget = findWidget(stackNode, "input_mode");
if (modeWidget) modeWidget.value = "text";
const countWidget = findWidget(stackNode, "lora_count");
if (countWidget) countWidget.value = group.loras.length;
for (let i = 0; i < group.loras.length; i++) {
const textWidget = findWidget(stackNode, `lora_name_text_${i + 1}`);
if (textWidget) textWidget.value = group.loras[i].name;
const strengthWidget = findWidget(stackNode, `strength_${i + 1}`);
if (strengthWidget) strengthWidget.value = group.loras[i].strength;
}
}
+1086 -218
View File
File diff suppressed because it is too large Load Diff