diff --git a/README.md b/README.md
index 9df5886a..229ff078 100644
--- a/README.md
+++ b/README.md
@@ -192,14 +192,14 @@ NODE_CLASS_MAPPINGS.update({
## Roadmap
-- [ ] System displaying information about failed custom nodes import.
-- [ ] Guide for missing nodes in ComfyUI vanilla nodes.
+- [x] System displaying information about failed custom nodes import.
+- [x] Guide for missing nodes in ComfyUI vanilla nodes.
+- [x] Collision checking system for nodes with the same ID across extensions.
- [ ] Auto migration for custom nodes with changed structures.
- [ ] Version control feature for nodes.
- [ ] List of currently used custom nodes.
- [ ] Template sharing system.
- [ ] 3rd party API system.
-- [ ] Collision checking system for nodes with the same ID across extensions.
# Disclaimer
diff --git a/__init__.py b/__init__.py
index 8d910f08..5bcdc1c0 100644
--- a/__init__.py
+++ b/__init__.py
@@ -13,8 +13,10 @@ from tqdm.auto import tqdm
import concurrent
import ssl
from urllib.parse import urlparse
+import http.client
+import re
-version = "V1.3"
+version = "V1.4"
print(f"### Loading: ComfyUI-Manager ({version})")
@@ -84,6 +86,7 @@ from torchvision.datasets.utils import download_url
comfy_ui_required_revision = 1240
comfy_ui_revision = "Unknown"
+comfy_ui_commit_date = ""
comfy_path = os.path.dirname(folder_paths.__file__)
custom_nodes_path = os.path.join(comfy_path, 'custom_nodes')
@@ -244,6 +247,8 @@ def try_install_script(url, repo_path, install_cmd):
def print_comfyui_version():
global comfy_ui_revision
+ global comfy_ui_commit_date
+
try:
repo = git.Repo(os.path.dirname(folder_paths.__file__))
@@ -257,10 +262,11 @@ def print_comfyui_version():
except:
pass
+ comfy_ui_commit_date = repo.head.commit.committed_datetime.date()
if current_branch == "master":
- print(f"### ComfyUI Revision: {comfy_ui_revision} [{git_hash[:8]}] | Released on '{repo.head.commit.committed_datetime.date()}'")
+ print(f"### ComfyUI Revision: {comfy_ui_revision} [{git_hash[:8]}] | Released on '{comfy_ui_commit_date}'")
else:
- print(f"### ComfyUI Revision: {comfy_ui_revision} on '{current_branch}' [{git_hash[:8]}] | Released on '{repo.head.commit.committed_datetime.date()}'")
+ print(f"### ComfyUI Revision: {comfy_ui_revision} on '{current_branch}' [{git_hash[:8]}] | Released on '{comfy_ui_commit_date}'")
except:
print("### ComfyUI Revision: UNKNOWN (The currently installed ComfyUI is not a Git repository)")
@@ -531,10 +537,15 @@ def check_a_custom_node_installed(item, do_fetch=False, do_update_check=True, do
try:
if do_update_check and git_repo_has_updates(dir_path, do_fetch, do_update):
item['installed'] = 'Update'
+ elif sys.__comfyui_manager_is_import_failed_extension(dir_name):
+ item['installed'] = 'Fail'
else:
item['installed'] = 'True'
except:
- item['installed'] = 'True'
+ if sys.__comfyui_manager_is_import_failed_extension(dir_name):
+ item['installed'] = 'Fail'
+ else:
+ item['installed'] = 'True'
elif os.path.exists(dir_path + ".disabled"):
item['installed'] = 'Disabled'
@@ -554,7 +565,10 @@ def check_a_custom_node_installed(item, do_fetch=False, do_update_check=True, do
file_path = os.path.join(base_path, dir_name)
if os.path.exists(file_path):
- item['installed'] = 'True'
+ if sys.__comfyui_manager_is_import_failed_extension(dir_name):
+ item['installed'] = 'Fail'
+ else:
+ item['installed'] = 'True'
elif os.path.exists(file_path + ".disabled"):
item['installed'] = 'Disabled'
else:
@@ -1421,6 +1435,37 @@ async def channel_url_list(request):
return web.Response(status=200)
+
+@server.PromptServer.instance.routes.get("/manager/notice")
+async def get_notice(request):
+ url = "github.com"
+ path = "/ltdrdata/ltdrdata.github.io/wiki/News"
+
+ conn = http.client.HTTPSConnection(url)
+ conn.request("GET", path)
+
+ response = conn.getresponse()
+
+ try:
+ if response.status == 200:
+ html_content = response.read().decode('utf-8')
+
+ pattern = re.compile(r'
([\s\S]*?)
')
+ match = pattern.search(html_content)
+
+ if match:
+ markdown_content = match.group(1)
+ markdown_content += f"
ComfyUI: {comfy_ui_revision} ({comfy_ui_commit_date})"
+ markdown_content += f"
Manager: {version}"
+ return web.Response(text=markdown_content, status=200)
+ else:
+ return web.Response(text="Unable to retrieve Notice", status=200)
+ else:
+ return web.Response(text="Unable to retrieve Notice", status=200)
+ finally:
+ conn.close()
+
+
def get_matrix_auth():
if not os.path.exists(os.path.join(folder_paths.base_path, "matrix_auth")):
return None
diff --git a/extension-node-map.json b/extension-node-map.json
index 1e874ed0..9ba5faa3 100644
--- a/extension-node-map.json
+++ b/extension-node-map.json
@@ -2565,6 +2565,138 @@
"title_aux": "comfy-nodes"
}
],
+ "https://github.com/comfyanonymous/ComfyUI": [
+ [
+ "BasicScheduler",
+ "CLIPLoader",
+ "CLIPMergeSimple",
+ "CLIPSave",
+ "CLIPSetLastLayer",
+ "CLIPTextEncode",
+ "CLIPTextEncodeSDXL",
+ "CLIPTextEncodeSDXLRefiner",
+ "CLIPVisionEncode",
+ "CLIPVisionLoader",
+ "Canny",
+ "CheckpointLoader",
+ "CheckpointLoaderSimple",
+ "CheckpointSave",
+ "ConditioningAverage",
+ "ConditioningCombine",
+ "ConditioningConcat",
+ "ConditioningSetArea",
+ "ConditioningSetAreaPercentage",
+ "ConditioningSetMask",
+ "ConditioningSetTimestepRange",
+ "ConditioningZeroOut",
+ "ControlNetApply",
+ "ControlNetApplyAdvanced",
+ "ControlNetLoader",
+ "CropMask",
+ "DiffControlNetLoader",
+ "DiffusersLoader",
+ "DualCLIPLoader",
+ "EmptyImage",
+ "EmptyLatentImage",
+ "ExponentialScheduler",
+ "FeatherMask",
+ "FlipSigmas",
+ "FreeU",
+ "FreeU_V2",
+ "GLIGENLoader",
+ "GLIGENTextBoxApply",
+ "GrowMask",
+ "HyperTile",
+ "HypernetworkLoader",
+ "ImageBatch",
+ "ImageBlend",
+ "ImageBlur",
+ "ImageColorToMask",
+ "ImageCompositeMasked",
+ "ImageCrop",
+ "ImageInvert",
+ "ImageOnlyCheckpointLoader",
+ "ImagePadForOutpaint",
+ "ImageQuantize",
+ "ImageScale",
+ "ImageScaleBy",
+ "ImageScaleToTotalPixels",
+ "ImageSharpen",
+ "ImageToMask",
+ "ImageUpscaleWithModel",
+ "InvertMask",
+ "JoinImageWithAlpha",
+ "KSampler",
+ "KSamplerAdvanced",
+ "KSamplerSelect",
+ "KarrasScheduler",
+ "LatentAdd",
+ "LatentBlend",
+ "LatentComposite",
+ "LatentCompositeMasked",
+ "LatentCrop",
+ "LatentFlip",
+ "LatentFromBatch",
+ "LatentInterpolate",
+ "LatentMultiply",
+ "LatentRotate",
+ "LatentSubtract",
+ "LatentUpscale",
+ "LatentUpscaleBy",
+ "LoadImage",
+ "LoadImageMask",
+ "LoadLatent",
+ "LoraLoader",
+ "LoraLoaderModelOnly",
+ "MaskComposite",
+ "MaskToImage",
+ "ModelMergeAdd",
+ "ModelMergeBlocks",
+ "ModelMergeSimple",
+ "ModelMergeSubtract",
+ "ModelSamplingContinuousEDM",
+ "ModelSamplingDiscrete",
+ "PatchModelAddDownscale",
+ "PolyexponentialScheduler",
+ "PorterDuffImageComposite",
+ "PreviewImage",
+ "RebatchLatents",
+ "RepeatImageBatch",
+ "RepeatLatentBatch",
+ "RescaleCFG",
+ "SVD_img2vid_Conditioning",
+ "SamplerCustom",
+ "SamplerDPMPP_2M_SDE",
+ "SamplerDPMPP_SDE",
+ "SaveAnimatedPNG",
+ "SaveAnimatedWEBP",
+ "SaveImage",
+ "SaveLatent",
+ "SetLatentNoiseMask",
+ "SolidMask",
+ "SplitImageWithAlpha",
+ "SplitSigmas",
+ "StyleModelApply",
+ "StyleModelLoader",
+ "TomePatchModel",
+ "UNETLoader",
+ "UpscaleModelLoader",
+ "VAEDecode",
+ "VAEDecodeTiled",
+ "VAEEncode",
+ "VAEEncodeForInpaint",
+ "VAEEncodeTiled",
+ "VAELoader",
+ "VAESave",
+ "VPScheduler",
+ "VideoLinearCFGGuidance",
+ "unCLIPCheckpointLoader",
+ "unCLIPConditioning"
+ ],
+ {
+ "title_aux": "ComfyUI"
+ }
+ ],
"https://github.com/comfyanonymous/ComfyUI_experiments": [
[
"ModelMergeBlockNumber",
@@ -4274,6 +4406,7 @@
[
"Auto Merge Block Weighted",
"CLIPMergeSimple",
+ "CheckpointSave",
"ModelMergeBlocks",
"ModelMergeSimple"
],
diff --git a/js/comfyui-manager.js b/js/comfyui-manager.js
index 914dec96..c26d16c8 100644
--- a/js/comfyui-manager.js
+++ b/js/comfyui-manager.js
@@ -28,6 +28,16 @@ docStyle.innerHTML = `
text-align: center;
height: 45px;
}
+
+.cm-notice-board {
+ width: 250px;
+ height: 130px;
+ overflow: auto;
+ color: var(--input-text);
+ border: 1px solid #ccc;
+ padding: 10px;
+ overflow-x: hidden;
+};
`;
document.head.appendChild(docStyle);
@@ -79,6 +89,14 @@ async function init_badge_mode() {
.then(data => { badge_mode = data; })
}
+async function init_notice(notice) {
+ api.fetchApi('/manager/notice')
+ .then(response => response.text())
+ .then(data => {
+ notice.innerHTML = data;
+ })
+}
+
await init_badge_mode();
@@ -436,7 +454,7 @@ class ManagerMenuDialog extends ComfyDialog {
}
createControlsRight() {
- return [
+ const elts = [
$el("button", {
type: "button",
textContent: "ComfyUI Community Manual",
@@ -514,7 +532,16 @@ class ManagerMenuDialog extends ComfyDialog {
textContent: "ComfyUI Nodes Info",
onclick: () => { window.open("https://ltdrdata.github.io/", "comfyui-node-info"); }
}),
+ $el("br", {}, []),
];
+
+ var textarea = document.createElement("div");
+ textarea.className = "cm-notice-board";
+ elts.push(textarea);
+
+ init_notice(textarea);
+
+ return elts;
}
constructor() {
@@ -647,6 +674,10 @@ app.registerExtension({
if (nicknames[nodeData.name.trim()]) {
let nick = nicknames[nodeData.name.trim()];
+ if (nick == 'ComfyUI') {
+ nick = "🦊"
+ }
+
if (nick.length > 25) {
text += nick.substring(0, 23) + "..";
}
@@ -691,6 +722,10 @@ app.registerExtension({
if (nicknames[node.type.trim()]) {
let nick = nicknames[node.type.trim()];
+ if (nick == 'ComfyUI') {
+ nick = "🦊"
+ }
+
if (nick.length > 25) {
text += nick.substring(0, 23) + "..";
}
diff --git a/js/custom-nodes-downloader.js b/js/custom-nodes-downloader.js
index fd8553e5..a2f3f5a3 100644
--- a/js/custom-nodes-downloader.js
+++ b/js/custom-nodes-downloader.js
@@ -29,6 +29,53 @@ async function getCustomnodeMappings() {
return data;
}
+async function getConflictMappings() {
+ var mode = "url";
+ if(manager_instance.local_mode_checkbox.checked)
+ mode = "local";
+
+ const response = await api.fetchApi(`/customnode/getmappings?mode=${mode}`);
+
+ const data = await response.json();
+
+ let node_to_extensions_map = {};
+
+ for(let k in data) {
+ for(let i in data[k][0]) {
+ let node = data[k][0][i];
+ let l = node_to_extensions_map[node];
+ if(!l) {
+ l = [];
+ node_to_extensions_map[node] = l;
+ }
+ l.push(k);
+ }
+ }
+
+ let conflict_map = {};
+ for(let node in node_to_extensions_map) {
+ if(node_to_extensions_map[node].length > 1) {
+ for(let i in node_to_extensions_map[node]) {
+ let extension = node_to_extensions_map[node][i];
+ let l = conflict_map[extension];
+
+ if(!l) {
+ l = [];
+ conflict_map[extension] = l;
+ }
+
+ for(let j in node_to_extensions_map[node]) {
+ let extension2 = node_to_extensions_map[node][j];
+ if(extension != extension2)
+ l.push([node, extension2]);
+ }
+ }
+ }
+ }
+
+ return conflict_map;
+}
+
async function getUnresolvedNodesInComponent() {
try {
var mode = "url";
@@ -180,6 +227,8 @@ export class CustomNodesInstaller extends ComfyDialog {
// invalidate
this.data = (await getCustomNodes()).custom_nodes;
+ this.conflict_mappings = await getConflictMappings();
+
if(this.is_missing_node_mode)
this.data = await this.filter_missing_node(this.data);
@@ -369,6 +418,7 @@ export class CustomNodesInstaller extends ComfyDialog {
var data1 = document.createElement('td');
data1.style.textAlign = "center";
data1.innerHTML = i+1;
+
var data2 = document.createElement('td');
data2.style.maxWidth = "100px";
data2.className = "cm-node-author"
@@ -376,14 +426,43 @@ export class CustomNodesInstaller extends ComfyDialog {
data2.style.whiteSpace = "nowrap";
data2.style.overflow = "hidden";
data2.style.textOverflow = "ellipsis";
+
var data3 = document.createElement('td');
data3.style.maxWidth = "200px";
data3.style.wordWrap = "break-word";
data3.className = "cm-node-name"
data3.innerHTML = ` ${data.title}`;
+ if(data.installed == 'Fail')
+ data3.innerHTML = ' (IMPORT FAILED)' + data3.innerHTML;
+
var data4 = document.createElement('td');
data4.innerHTML = data.description;
data4.className = "cm-node-desc"
+
+ let conflicts = this.conflict_mappings[data.files[0]];
+ if(conflicts) {
+ let buf = '
Conflicted Nodes:
';
+ for(let k in conflicts) {
+ let node_name = conflicts[k][0];
+
+ let extension_name = conflicts[k][1].split('/').pop();
+ if(extension_name.endsWith('/')) {
+ extension_name = extension_name.slice(0, -1);
+ }
+ if(node_name.endsWith('.git')) {
+ extension_name = extension_name.slice(0, -4);
+ }
+
+ buf += `${node_name} [${extension_name}], `;
+ }
+
+ if(buf.endsWith(', ')) {
+ buf = buf.slice(0, -2);
+ }
+ buf += "";
+ data4.innerHTML += buf;
+ }
+
var data5 = document.createElement('td');
data5.style.textAlign = "center";
@@ -424,6 +503,7 @@ export class CustomNodesInstaller extends ComfyDialog {
installBtn.innerHTML = 'Uninstall';
installBtn.style.backgroundColor = 'red';
break;
+ case 'Fail':
case 'True':
installBtn3 = document.createElement('button');
installBtn3.innerHTML = 'Disable';
@@ -441,7 +521,7 @@ export class CustomNodesInstaller extends ComfyDialog {
installBtn.style.color = 'white';
break;
default:
- installBtn.innerHTML = 'Try Install';
+ installBtn.innerHTML = `Try Install${data.installed}`;
installBtn.style.backgroundColor = 'Gray';
installBtn.style.color = 'white';
}
@@ -479,7 +559,10 @@ export class CustomNodesInstaller extends ComfyDialog {
data5.appendChild(installBtn);
- dataRow.style.backgroundColor = "var(--bg-color)";
+ if(data.installed == 'Fail')
+ dataRow.style.backgroundColor = "#880000";
+ else
+ dataRow.style.backgroundColor = "var(--bg-color)";
dataRow.style.color = "var(--fg-color)";
dataRow.style.textAlign = "left";
@@ -548,6 +631,7 @@ export class CustomNodesInstaller extends ComfyDialog {
{ value:'Update', text:'Filter: update' },
{ value:'True', text:'Filter: installed' },
{ value:'False', text:'Filter: not-installed' },
+ { value:'Fail', text:'Filter: import failed' },
];
items.forEach(item => {
diff --git a/node_db/new/extension-node-map.json b/node_db/new/extension-node-map.json
index 1e874ed0..9ba5faa3 100644
--- a/node_db/new/extension-node-map.json
+++ b/node_db/new/extension-node-map.json
@@ -2565,6 +2565,138 @@
"title_aux": "comfy-nodes"
}
],
+ "https://github.com/comfyanonymous/ComfyUI": [
+ [
+ "BasicScheduler",
+ "CLIPLoader",
+ "CLIPMergeSimple",
+ "CLIPSave",
+ "CLIPSetLastLayer",
+ "CLIPTextEncode",
+ "CLIPTextEncodeSDXL",
+ "CLIPTextEncodeSDXLRefiner",
+ "CLIPVisionEncode",
+ "CLIPVisionLoader",
+ "Canny",
+ "CheckpointLoader",
+ "CheckpointLoaderSimple",
+ "CheckpointSave",
+ "ConditioningAverage",
+ "ConditioningCombine",
+ "ConditioningConcat",
+ "ConditioningSetArea",
+ "ConditioningSetAreaPercentage",
+ "ConditioningSetMask",
+ "ConditioningSetTimestepRange",
+ "ConditioningZeroOut",
+ "ControlNetApply",
+ "ControlNetApplyAdvanced",
+ "ControlNetLoader",
+ "CropMask",
+ "DiffControlNetLoader",
+ "DiffusersLoader",
+ "DualCLIPLoader",
+ "EmptyImage",
+ "EmptyLatentImage",
+ "ExponentialScheduler",
+ "FeatherMask",
+ "FlipSigmas",
+ "FreeU",
+ "FreeU_V2",
+ "GLIGENLoader",
+ "GLIGENTextBoxApply",
+ "GrowMask",
+ "HyperTile",
+ "HypernetworkLoader",
+ "ImageBatch",
+ "ImageBlend",
+ "ImageBlur",
+ "ImageColorToMask",
+ "ImageCompositeMasked",
+ "ImageCrop",
+ "ImageInvert",
+ "ImageOnlyCheckpointLoader",
+ "ImagePadForOutpaint",
+ "ImageQuantize",
+ "ImageScale",
+ "ImageScaleBy",
+ "ImageScaleToTotalPixels",
+ "ImageSharpen",
+ "ImageToMask",
+ "ImageUpscaleWithModel",
+ "InvertMask",
+ "JoinImageWithAlpha",
+ "KSampler",
+ "KSamplerAdvanced",
+ "KSamplerSelect",
+ "KarrasScheduler",
+ "LatentAdd",
+ "LatentBlend",
+ "LatentComposite",
+ "LatentCompositeMasked",
+ "LatentCrop",
+ "LatentFlip",
+ "LatentFromBatch",
+ "LatentInterpolate",
+ "LatentMultiply",
+ "LatentRotate",
+ "LatentSubtract",
+ "LatentUpscale",
+ "LatentUpscaleBy",
+ "LoadImage",
+ "LoadImageMask",
+ "LoadLatent",
+ "LoraLoader",
+ "LoraLoaderModelOnly",
+ "MaskComposite",
+ "MaskToImage",
+ "ModelMergeAdd",
+ "ModelMergeBlocks",
+ "ModelMergeSimple",
+ "ModelMergeSubtract",
+ "ModelSamplingContinuousEDM",
+ "ModelSamplingDiscrete",
+ "PatchModelAddDownscale",
+ "PolyexponentialScheduler",
+ "PorterDuffImageComposite",
+ "PreviewImage",
+ "RebatchLatents",
+ "RepeatImageBatch",
+ "RepeatLatentBatch",
+ "RescaleCFG",
+ "SVD_img2vid_Conditioning",
+ "SamplerCustom",
+ "SamplerDPMPP_2M_SDE",
+ "SamplerDPMPP_SDE",
+ "SaveAnimatedPNG",
+ "SaveAnimatedWEBP",
+ "SaveImage",
+ "SaveLatent",
+ "SetLatentNoiseMask",
+ "SolidMask",
+ "SplitImageWithAlpha",
+ "SplitSigmas",
+ "StyleModelApply",
+ "StyleModelLoader",
+ "TomePatchModel",
+ "UNETLoader",
+ "UpscaleModelLoader",
+ "VAEDecode",
+ "VAEDecodeTiled",
+ "VAEEncode",
+ "VAEEncodeForInpaint",
+ "VAEEncodeTiled",
+ "VAELoader",
+ "VAESave",
+ "VPScheduler",
+ "VideoLinearCFGGuidance",
+ "unCLIPCheckpointLoader",
+ "unCLIPConditioning"
+ ],
+ {
+ "title_aux": "ComfyUI"
+ }
+ ],
"https://github.com/comfyanonymous/ComfyUI_experiments": [
[
"ModelMergeBlockNumber",
@@ -4274,6 +4406,7 @@
[
"Auto Merge Block Weighted",
"CLIPMergeSimple",
+ "CheckpointSave",
"ModelMergeBlocks",
"ModelMergeSimple"
],
diff --git a/prestartup_script.py b/prestartup_script.py
index 94230b3d..c86a17c3 100644
--- a/prestartup_script.py
+++ b/prestartup_script.py
@@ -9,6 +9,7 @@ import locale
message_collapses = []
+import_failed_extensions = set()
def register_message_collapse(f):
@@ -16,10 +17,16 @@ def register_message_collapse(f):
message_collapses.append(f)
+def is_import_failed_extension(x):
+ global import_failed_extensions
+ return x in import_failed_extensions
+
+
sys.__comfyui_manager_register_message_collapse = register_message_collapse
+sys.__comfyui_manager_is_import_failed_extension = is_import_failed_extension
comfyui_manager_path = os.path.dirname(__file__)
-custom_nodes_path = os.path.join(comfyui_manager_path, "..")
+custom_nodes_path = os.path.abspath(os.path.join(comfyui_manager_path, ".."))
startup_script_path = os.path.join(comfyui_manager_path, "startup-scripts")
restore_snapshot_path = os.path.join(startup_script_path, "restore-snapshot.json")
git_script_path = os.path.join(comfyui_manager_path, "git_helper.py")
@@ -78,7 +85,12 @@ try:
original_stdout = sys.stdout
original_stderr = sys.stderr
- tqdm = r'\d+%.*\[(.*?)\]'
+ pat_tqdm = r'\d+%.*\[(.*?)\]'
+ pat_import_fail = r'seconds \(IMPORT FAILED\):'
+ pat_custom_node = r'[/\\]custom_nodes[/\\](.*)$'
+
+ is_start_mode = True
+ is_import_fail_mode = False
log_file = open(f"comfyui{postfix}.log", "w", encoding="utf-8")
log_lock = threading.Lock()
@@ -99,11 +111,30 @@ try:
raise ValueError("The object does not have a fileno method")
def write(self, message):
+ global is_start_mode
+ global is_import_fail_mode
+
if any(f(message) for f in message_collapses):
return
+ if is_start_mode:
+ if is_import_fail_mode:
+ match = re.search(pat_custom_node, message)
+ if match:
+ import_failed_extensions.add(match.group(1))
+ is_import_fail_mode = False
+ else:
+ match = re.search(pat_import_fail, message)
+ if match:
+ is_import_fail_mode = True
+ else:
+ is_import_fail_mode = False
+
+ if 'Starting server' in message:
+ is_start_mode = False
+
if not self.is_stdout:
- match = re.search(tqdm, message)
+ match = re.search(pat_tqdm, message)
if match:
message = re.sub(r'([#|])\d', r'\1▌', message)
message = re.sub('#', 'â–ˆ', message)
diff --git a/scanner.py b/scanner.py
index 37664b9a..8ac6a925 100644
--- a/scanner.py
+++ b/scanner.py
@@ -5,9 +5,12 @@ from git import Repo
from torchvision.datasets.utils import download_url
import concurrent
-builtin_nodes = ["KSampler", "CheckpointSave"]
+builtin_nodes = set()
+
+
+def scan_in_file(filename, is_builtin=False):
+ global builtin_nodes
-def scan_in_file(filename):
try:
with open(filename, encoding='utf-8') as file:
code = file.read()
@@ -63,9 +66,12 @@ def scan_in_file(filename):
key, value = line[1:].strip().split(':')
metadata[key.strip()] = value.strip()
- for x in builtin_nodes:
- if x in nodes:
- nodes.remove(x)
+ if is_builtin:
+ builtin_nodes += set(nodes)
+ else:
+ for x in builtin_nodes:
+ if x in nodes:
+ nodes.remove(x)
return nodes, metadata
@@ -113,7 +119,9 @@ def get_git_urls_from_json(json_file):
if node.get('install_type') == 'git-clone':
files = node.get('files', [])
if files:
- git_clone_files.append((files[0],node.get('title')))
+ git_clone_files.append((files[0], node.get('title')))
+
+ git_clone_files.append(("https://github.com/comfyanonymous/ComfyUI", "ComfyUI"))
return git_clone_files
@@ -190,7 +198,7 @@ def update_custom_nodes():
with concurrent.futures.ThreadPoolExecutor(10) as executor:
executor.map(download_and_store_info, py_url_titles)
-
+
return node_info
@@ -198,6 +206,10 @@ def gen_json(node_info):
# scan from .py file
node_files, node_dirs = get_nodes(".tmp")
+ comfyui_path = os.path.abspath(os.path.join('.tmp', "ComfyUI"))
+ node_dirs.remove(comfyui_path)
+ node_dirs = [comfyui_path] + node_dirs
+
data = {}
for dirname in node_dirs:
py_files = get_py_file_paths(dirname)
@@ -205,7 +217,7 @@ def gen_json(node_info):
nodes = set()
for py in py_files:
- nodes_in_file, metadata_in_file = scan_in_file(py)
+ nodes_in_file, metadata_in_file = scan_in_file(py, dirname == "ComfyUI")
nodes.update(nodes_in_file)
metadata.update(metadata_in_file)