ComfyUI-Manager/js/workflow-metadata.js
Dr.Lt.Data 0202cf07d5
revise /customnode/installed api (#1398)
* revise /customnode/installed

improved: don't fetch data from cnr for the api
improved: change format {<cnr id>: <version>} -> {<module>: [<version>, <cnr id>]}

* fix condition

* improved: add `mode=imported` for startup snapshot

`/customnode/installed` - current snapshot
`/customnode/installed?mode=imported` - startup snapshot

* improved: move cache dir to user directory

* modified: /customnodes/installed
- show whole nodes including disabled
- format changed `key -> list` to `key -> dict`

* fixed: doesn't show disabled node pack properly.

* Update workflow-metadata.js

---------

Co-authored-by: huchenlei <huchenlei@proton.me>
2025-01-08 19:50:58 -05:00

89 lines
2.7 KiB
JavaScript

/**
* 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";
import { api } from "../../scripts/api.js";
class WorkflowMetadataExtension {
constructor() {
this.name = "Comfy.CustomNodesManager.WorkflowMetadata";
this.installedNodes = {};
this.comfyCoreVersion = null;
}
/**
* Get the installed nodes info
* @returns {Promise<Record<string, {ver: string, cnr_id: string, enabled: boolean}>>} The mapping from node name to its info.
* ver can either be a git commit hash or a semantic version such as "1.0.0"
* cnr_id is the id of the node in the ComfyRegistry
* enabled is true if the node is enabled, false if it is disabled
*/
async getInstalledNodes() {
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<Record<string, string>>} The mapping from node name to version
*/
getGraphNodeVersions(graph) {
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") {
const nodePackageName = modules[1];
const nodeInfo =
this.installedNodes[nodePackageName] ??
this.installedNodes[nodePackageName.toLowerCase()];
nodeVersions[nodePackageName] = nodeInfo.ver;
} 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.installedNodes = await this.getInstalledNodes();
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());