feat(recipe): send embedded recipe workflow to ComfyUI canvas

This commit is contained in:
Will Miao
2026-08-20 22:18:13 +08:00
parent 0905e2be6e
commit 3ebf256c5d
24 changed files with 1145 additions and 27 deletions
+52
View File
@@ -218,6 +218,10 @@ app.registerExtension({
this.applyWidgetUpdate(event?.detail ?? {});
});
api.addEventListener("lm_load_workflow", (event) => {
this.loadWorkflowFromMessage(event?.detail ?? {});
});
window.addEventListener("lm_marker_changed", () => {
this.refreshRegistry();
});
@@ -415,6 +419,54 @@ app.registerExtension({
}
},
/**
* Load a workflow received from the backend onto the ComfyUI canvas.
*
* The payload (`detail`) is expected to be:
* { workflow: <workflow JSON>, name: <string>, recipe_id: <string> }
*
* Two formats are supported, detected by the presence of `class_type`
* entries (API/prompt format: { node_id: { class_type, inputs } }) versus
* the UI format ({ nodes: [...], links: [...] }).
*
* @param {Object} detail - message payload from the backend
*/
async loadWorkflowFromMessage(detail) {
let workflow = detail?.workflow;
if (!workflow) {
console.warn("LoRA Manager: lm_load_workflow received without a workflow payload", detail);
return;
}
if (typeof workflow === "string") {
try {
workflow = JSON.parse(workflow);
} catch (error) {
console.warn("LoRA Manager: lm_load_workflow carried a non-JSON workflow string", error);
return;
}
}
// Mirror ComfyUI_frontend's isApiJson detection: API format maps every
// node id to an object with a string class_type; UI format has arrays
// of nodes/links instead.
const values = Object.values(workflow);
const isApiFormat = values.length > 0 && values.every((v) => v && typeof v.class_type === "string");
const workflowName = detail.name || "Recipe Workflow";
try {
if (isApiFormat) {
await app.loadApiJson(workflow, workflowName);
} else {
await app.loadGraphData(workflow, true, true, workflowName, { openSource: "file_button" });
}
this._log("workflow loaded from backend message (%s): %s", isApiFormat ? "api" : "graph", workflowName);
} catch (error) {
console.error("LoRA Manager: failed to load workflow from backend message", error);
}
},
applyWidgetUpdate(message) {
const nodeId = message?.node_id ?? message?.id;
const graphId = message?.graph_id;