From fd29dc513340f9dc36a049888e87770d5771a5d4 Mon Sep 17 00:00:00 2001 From: huchenlei Date: Thu, 19 Dec 2024 15:19:00 -0800 Subject: [PATCH 1/3] Add extension to attach node versions --- js/workflow-metadata.js | 72 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 js/workflow-metadata.js diff --git a/js/workflow-metadata.js b/js/workflow-metadata.js new file mode 100644 index 00000000..d3b07d84 --- /dev/null +++ b/js/workflow-metadata.js @@ -0,0 +1,72 @@ +/** + * Attaches metadata to the workflow on save + * - custom node pack version to all custom nodes used in the workflow + */ + +import { app } from "../../scripts/app.js"; +import { api } from "../../scripts/api.js"; + +class WorkflowMetadataExtension { + constructor() { + this.name = "Comfy.CustomNodesManager.WorkflowMetadata"; + this.installedNodeVersions = {}; + this.comfyCoreVersion = null; + } + + /** + * Get the installed node versions + * @returns {Promise>} The mapping from node name to version + * version can either be a git commit hash or a semantic version such as "1.0.0" + */ + async getInstalledNodeVersions() { + const res = await api.fetchApi("/customnode/installed"); + return await res.json(); + } + + /** + * Get the node versions for the given graph + * @param {LGraph} graph The graph to get the node versions for + * @returns {Promise>} The mapping from node name to version + */ + getGraphNodeVersions(graph) { + const nodeVersions = {}; + for (const node of graph.nodes) { + const nodeData = node.constructor.nodeData; + const modules = nodeData.python_module.split("."); + + if (modules[0] === "custom_nodes") { + const nodePackageName = modules[1].split("@")[0]; + const nodeVersion = this.installedNodeVersions[nodePackageName]; + nodeVersions[nodePackageName] = nodeVersion; + } else if (["nodes", "comfy_extras"].includes(modules[0])) { + nodeVersions["comfy-core"] = this.comfyCoreVersion; + } else { + console.warn(`Unknown node source: ${nodeData.python_module}`); + } + } + return nodeVersions; + } + + async init() { + const extension = this; + this.installedNodeVersions = await this.getInstalledNodeVersions(); + this.comfyCoreVersion = (await api.getSystemStats()).system.comfyui_version; + + // Attach metadata when app.graphToPrompt is called. + const originalSerialize = LGraph.prototype.serialize; + LGraph.prototype.serialize = function () { + const workflow = originalSerialize.apply(this, arguments); + + // Add metadata to the workflow + if (!workflow.extra) { + workflow.extra = {}; + } + const graph = this; + workflow.extra["node_versions"] = extension.getGraphNodeVersions(graph); + + return workflow; + }; + } +} + +app.registerExtension(new WorkflowMetadataExtension()); From c2ac84c3d3f7f9de965afd7896e03b00ca06f07e Mon Sep 17 00:00:00 2001 From: huchenlei Date: Thu, 19 Dec 2024 15:35:11 -0800 Subject: [PATCH 2/3] nit --- js/workflow-metadata.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/js/workflow-metadata.js b/js/workflow-metadata.js index d3b07d84..d1efc3a2 100644 --- a/js/workflow-metadata.js +++ b/js/workflow-metadata.js @@ -1,6 +1,14 @@ /** * Attaches metadata to the workflow on save * - custom node pack version to all custom nodes used in the workflow + * + * Example metadata: + "extra": { + "node_versions": { + "comfy-core": "v0.3.8-4-g0b2eb7f", + "comfyui-easy-use": "1.2.5" + } + }, */ import { app } from "../../scripts/app.js"; From 0ae2b7f338f2d3fff69157182f56f765b2e06686 Mon Sep 17 00:00:00 2001 From: huchenlei Date: Thu, 19 Dec 2024 15:39:24 -0800 Subject: [PATCH 3/3] nit --- js/workflow-metadata.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/js/workflow-metadata.js b/js/workflow-metadata.js index d1efc3a2..20d03df6 100644 --- a/js/workflow-metadata.js +++ b/js/workflow-metadata.js @@ -40,6 +40,10 @@ class WorkflowMetadataExtension { const nodeVersions = {}; for (const node of graph.nodes) { const nodeData = node.constructor.nodeData; + // Frontend only nodes don't have nodeData + if (!nodeData) { + continue; + } const modules = nodeData.python_module.split("."); if (modules[0] === "custom_nodes") {