diff --git a/__init__.py b/__init__.py index 65d4625..d5142f4 100644 --- a/__init__.py +++ b/__init__.py @@ -29,7 +29,7 @@ except: print(f"[WARN] ComfyUI-Manager: Your ComfyUI version is outdated. Please update to the latest version.") -version = [2, 7, 2] +version = [2, 8] version_str = f"V{version[0]}.{version[1]}" + (f'.{version[2]}' if len(version) > 2 else '') print(f"### Loading: ComfyUI-Manager ({version_str})") @@ -777,9 +777,47 @@ def check_custom_nodes_installed(json_obj, do_fetch=False, do_update_check=True, print(f"\x1b[2K\rUpdate check done.") +def nickname_filter(json_obj): + preemptions_map = {} + + for k, x in json_obj.items(): + if 'preemptions' in x[1]: + for y in x[1]['preemptions']: + preemptions_map[y] = k + elif k.endswith("/ComfyUI"): + for y in x[0]: + preemptions_map[y] = k + + updates = {} + for k, x in json_obj.items(): + removes = set() + for y in x[0]: + k2 = preemptions_map.get(y) + if k2 is not None and k != k2: + removes.add(y) + + if len(removes) > 0: + updates[k] = [y for y in x[0] if y not in removes] + + for k, v in updates.items(): + json_obj[k][0] = v + + return json_obj + + @server.PromptServer.instance.routes.get("/customnode/getmappings") async def fetch_customnode_mappings(request): - json_obj = await get_data_by_mode(request.rel_url.query["mode"], 'extension-node-map.json') + mode = request.rel_url.query["mode"] + + nickname_mode = False + if mode == "nickname": + mode = "local" + nickname_mode = True + + json_obj = await get_data_by_mode(mode, 'extension-node-map.json') + + if nickname_mode: + json_obj = nickname_filter(json_obj) all_nodes = set() patterns = [] diff --git a/custom-node-list.json b/custom-node-list.json index 4a494bf..d3c3670 100644 --- a/custom-node-list.json +++ b/custom-node-list.json @@ -1896,6 +1896,7 @@ "https://github.com/Ttl/ComfyUi_NNLatentUpscale" ], "install_type": "git-clone", + "preemptions": ["NNLatentUpscale"], "description": "Nodes:NNLatentUpscale, A custom ComfyUI node designed for rapid latent upscaling using a compact neural network, eliminating the need for VAE-based decoding and encoding." }, { diff --git a/extension-node-map.json b/extension-node-map.json index ae3620f..2bc61d3 100644 --- a/extension-node-map.json +++ b/extension-node-map.json @@ -247,15 +247,6 @@ "title_aux": "AnimateDiff" } ], - "https://github.com/AuroBit/ComfyUI-OOTDiffusion": [ - [ - "LoadOOTDPipeline", - "OOTDGenerate" - ], - { - "title_aux": "ComfyUI OOTDiffusion" - } - ], "https://github.com/AustinMroz/ComfyUI-SpliceTools": [ [ "LogSigmas", @@ -682,7 +673,7 @@ "author": "CRE8IT GmbH", "description": "This extension offers various nodes.", "nickname": "cre8Nodes", - "title": "cr8SerialPrompter", + "title": "cr8ImageSizer", "title_aux": "ComfyUI-Cre8it-Nodes" } ], @@ -1060,10 +1051,12 @@ ], "https://github.com/Haoming02/comfyui-diffusion-cg": [ [ + "Hook Recenter", + "Hook Recenter XL", "Normalization", "NormalizationXL", - "Recenter", - "Recenter XL" + "Tensor Debug", + "Unhook Recenter" ], { "title_aux": "ComfyUI Diffusion Color Grading" @@ -2015,6 +2008,7 @@ ], "https://github.com/RomanKuschanow/ComfyUI-Advanced-Latent-Control": [ [ + "KSamplerMirroring", "LatentMirror", "LatentShift" ], @@ -2825,6 +2819,9 @@ "NNLatentUpscale" ], { + "preemptions": [ + "NNLatentUpscale" + ], "title_aux": "ComfyUI Neural Network Latent Upscale" } ], @@ -4948,14 +4945,14 @@ ], "https://github.com/davask/ComfyUI-MarasIT-Nodes": [ [ - "MarasitBusNode", "MarasitAnyBusNode", + "MarasitBusNode", "MarasitBusPipeNode", "MarasitPipeNodeBasic", "MarasitUniversalBusNode" ], { - "title_aux": "🐰 MarasIT Nodes" + "title_aux": "\ud83d\udc30 MarasIT Nodes" } ], "https://github.com/dave-palt/comfyui_DSP_imagehelpers": [ @@ -5516,6 +5513,7 @@ ], "https://github.com/gokayfem/ComfyUI_VLM_nodes": [ [ + "AudioLDM2Node", "CreativeArtPromptGenerator", "Internlm", "Joytag", @@ -5531,6 +5529,7 @@ "LLavaSamplerSimple", "LlavaClipLoader", "MoonDream", + "PlayMusic", "PromptGenerateAPI", "SimpleText", "Suggester", @@ -8745,4 +8744,4 @@ "title_aux": "SDXLCustomAspectRatio" } ] -} +} \ No newline at end of file diff --git a/js/comfyui-manager.js b/js/comfyui-manager.js index 46cd592..7cbd8dd 100644 --- a/js/comfyui-manager.js +++ b/js/comfyui-manager.js @@ -147,13 +147,13 @@ docStyle.innerHTML = ` } .cm-notice-board > ul { - display: block; - list-style-type: disc; - margin-block-start: 1em; - margin-block-end: 1em; - margin-inline-start: 0px; - margin-inline-end: 0px; - padding-inline-start: 40px; + display: block; + list-style-type: disc; + margin-block-start: 1em; + margin-block-end: 1em; + margin-inline-start: 0px; + margin-inline-end: 0px; + padding-inline-start: 40px; } .cm-conflicted-nodes-text { @@ -378,7 +378,7 @@ await init_badge_mode(); await init_share_option(); async function fetchNicknames() { - const response1 = await api.fetchApi(`/customnode/getmappings?mode=local`); + const response1 = await api.fetchApi(`/customnode/getmappings?mode=nickname`); const mappings = await response1.json(); let result = {}; diff --git a/js/custom-nodes-downloader.js b/js/custom-nodes-downloader.js index 10d893e..aa2b054 100644 --- a/js/custom-nodes-downloader.js +++ b/js/custom-nodes-downloader.js @@ -154,7 +154,6 @@ export class CustomNodesInstaller extends ComfyDialog { async filter_missing_node(data) { const mappings = await getCustomnodeMappings(); - // build regex->url map const regex_to_url = []; for (let i in data) { @@ -165,11 +164,17 @@ export class CustomNodesInstaller extends ComfyDialog { } // build name->url map - const name_to_url = {}; + const name_to_urls = {}; for (const url in mappings) { const names = mappings[url]; + for(const name in names[0]) { - name_to_url[names[0][name]] = url; + let v = name_to_urls[names[0][name]]; + if(v == undefined) { + v = []; + name_to_urls[names[0][name]] = v; + } + v.push(url); } } @@ -194,9 +199,11 @@ export class CustomNodesInstaller extends ComfyDialog { continue; if (!registered_nodes.has(node_type)) { - const url = name_to_url[node_type.trim()]; - if(url) - missing_nodes.add(url); + const urls = name_to_urls[node_type.trim()]; + if(urls) + urls.forEach(url => { + missing_nodes.add(url); + }); else { for(let j in regex_to_url) { if(regex_to_url[j].regex.test(node_type)) { @@ -210,7 +217,7 @@ export class CustomNodesInstaller extends ComfyDialog { let unresolved_nodes = await getUnresolvedNodesInComponent(); for (let i in unresolved_nodes) { let node_type = unresolved_nodes[i]; - const url = name_to_url[node_type]; + const url = name_to_urls[node_type]; if(url) missing_nodes.add(url); } diff --git a/node_db/new/extension-node-map.json b/node_db/new/extension-node-map.json index 2062b50..2bc61d3 100644 --- a/node_db/new/extension-node-map.json +++ b/node_db/new/extension-node-map.json @@ -247,15 +247,6 @@ "title_aux": "AnimateDiff" } ], - "https://github.com/AuroBit/ComfyUI-OOTDiffusion": [ - [ - "LoadOOTDPipeline", - "OOTDGenerate" - ], - { - "title_aux": "ComfyUI OOTDiffusion" - } - ], "https://github.com/AustinMroz/ComfyUI-SpliceTools": [ [ "LogSigmas", @@ -682,7 +673,7 @@ "author": "CRE8IT GmbH", "description": "This extension offers various nodes.", "nickname": "cre8Nodes", - "title": "cr8SerialPrompter", + "title": "cr8ImageSizer", "title_aux": "ComfyUI-Cre8it-Nodes" } ], @@ -1060,10 +1051,12 @@ ], "https://github.com/Haoming02/comfyui-diffusion-cg": [ [ + "Hook Recenter", + "Hook Recenter XL", "Normalization", "NormalizationXL", - "Recenter", - "Recenter XL" + "Tensor Debug", + "Unhook Recenter" ], { "title_aux": "ComfyUI Diffusion Color Grading" @@ -2015,6 +2008,7 @@ ], "https://github.com/RomanKuschanow/ComfyUI-Advanced-Latent-Control": [ [ + "KSamplerMirroring", "LatentMirror", "LatentShift" ], @@ -2825,6 +2819,9 @@ "NNLatentUpscale" ], { + "preemptions": [ + "NNLatentUpscale" + ], "title_aux": "ComfyUI Neural Network Latent Upscale" } ], @@ -4948,13 +4945,14 @@ ], "https://github.com/davask/ComfyUI-MarasIT-Nodes": [ [ + "MarasitAnyBusNode", "MarasitBusNode", "MarasitBusPipeNode", "MarasitPipeNodeBasic", "MarasitUniversalBusNode" ], { - "title_aux": "MarasIT Nodes" + "title_aux": "\ud83d\udc30 MarasIT Nodes" } ], "https://github.com/dave-palt/comfyui_DSP_imagehelpers": [ @@ -5515,6 +5513,7 @@ ], "https://github.com/gokayfem/ComfyUI_VLM_nodes": [ [ + "AudioLDM2Node", "CreativeArtPromptGenerator", "Internlm", "Joytag", @@ -5530,6 +5529,7 @@ "LLavaSamplerSimple", "LlavaClipLoader", "MoonDream", + "PlayMusic", "PromptGenerateAPI", "SimpleText", "Suggester", diff --git a/scan.sh b/scan.sh index 1b3cc37..ef6e434 100755 --- a/scan.sh +++ b/scan.sh @@ -1,6 +1,6 @@ #!/bin/bash rm ~/.tmp/default/*.py > /dev/null 2>&1 -python scanner.py ~/.tmp/default +python scanner.py ~/.tmp/default $@ cp extension-node-map.json node_db/new/. echo Integrity check diff --git a/scanner.py b/scanner.py index 8b8d4de..7e81aa9 100644 --- a/scanner.py +++ b/scanner.py @@ -20,6 +20,8 @@ else: if not os.path.exists(temp_dir): os.makedirs(temp_dir) +skip_update = '--skip-update' in sys.argv + print(f"TEMP DIR: {temp_dir}") @@ -159,9 +161,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'), node.get('nodename_pattern'))) + git_clone_files.append((files[0], node.get('title'), node.get('preemptions'), node.get('nodename_pattern'))) - git_clone_files.append(("https://github.com/comfyanonymous/ComfyUI", "ComfyUI", None)) + git_clone_files.append(("https://github.com/comfyanonymous/ComfyUI", "ComfyUI", None, None)) return git_clone_files @@ -176,7 +178,7 @@ def get_py_urls_from_json(json_file): if node.get('install_type') == 'copy': files = node.get('files', []) if files: - py_files.append((files[0], node.get('title'), node.get('nodename_pattern'))) + py_files.append((files[0], node.get('title'), node.get('preemptions'), node.get('nodename_pattern'))) return py_files @@ -208,27 +210,31 @@ def update_custom_nodes(): node_info = {} - git_url_titles = get_git_urls_from_json('custom-node-list.json') + git_url_titles_preemptions = get_git_urls_from_json('custom-node-list.json') + + def process_git_url_title(url, title, preemptions, node_pattern): + if 'Jovimetrix' in title: + pass - def process_git_url_title(url, title, node_pattern): name = os.path.basename(url) if name.endswith(".git"): name = name[:-4] - node_info[name] = (url, title, node_pattern) - clone_or_pull_git_repository(url) + node_info[name] = (url, title, preemptions, node_pattern) + if not skip_update: + clone_or_pull_git_repository(url) with concurrent.futures.ThreadPoolExecutor(10) as executor: - for url, title, node_pattern in git_url_titles: - executor.submit(process_git_url_title, url, title, node_pattern) + for url, title, preemptions, node_pattern in git_url_titles_preemptions: + executor.submit(process_git_url_title, url, title, preemptions, node_pattern) py_url_titles_and_pattern = get_py_urls_from_json('custom-node-list.json') - def download_and_store_info(url_title_and_pattern): - url, title, node_pattern = url_title_and_pattern + def download_and_store_info(url_title_preemptions_and_pattern): + url, title, preemptions, node_pattern = url_title_preemptions_and_pattern name = os.path.basename(url) if name.endswith(".py"): - node_info[name] = (url, title, node_pattern) + node_info[name] = (url, title, preemptions, node_pattern) try: download_url(url, temp_dir) @@ -262,15 +268,24 @@ def gen_json(node_info): dirname = os.path.basename(dirname) - if len(nodes) > 0 or (dirname in node_info and node_info[dirname][2] is not None): + if 'Jovimetrix' in dirname: + pass + + if len(nodes) > 0 or (dirname in node_info and node_info[dirname][3] is not None): nodes = list(nodes) nodes.sort() if dirname in node_info: - git_url, title, node_pattern = node_info[dirname] + git_url, title, preemptions, node_pattern = node_info[dirname] + metadata['title_aux'] = title + + if preemptions is not None: + metadata['preemptions'] = preemptions + if node_pattern is not None: metadata['nodename_pattern'] = node_pattern + data[git_url] = (nodes, metadata) else: print(f"WARN: {dirname} is removed from custom-node-list.json") @@ -278,17 +293,22 @@ def gen_json(node_info): for file in node_files: nodes, metadata = scan_in_file(file) - if len(nodes) > 0 or (dirname in node_info and node_info[dirname][2] is not None): + if len(nodes) > 0 or (dirname in node_info and node_info[dirname][3] is not None): nodes = list(nodes) nodes.sort() file = os.path.basename(file) if file in node_info: - url, title, node_pattern = node_info[file] + url, title, preemptions, node_pattern = node_info[file] metadata['title_aux'] = title + + if preemptions is not None: + metadata['preemptions'] = preemptions + if node_pattern is not None: metadata['nodename_pattern'] = node_pattern + data[url] = (nodes, metadata) else: print(f"Missing info: {file}") @@ -299,7 +319,7 @@ def gen_json(node_info): for extension in extensions: node_list_json_path = os.path.join(temp_dir, extension, 'node_list.json') if os.path.exists(node_list_json_path): - git_url, title, node_pattern = node_info[extension] + git_url, title, preemptions, node_pattern = node_info[extension] with open(node_list_json_path, 'r', encoding='utf-8') as f: node_list_json = json.load(f) @@ -315,8 +335,13 @@ def gen_json(node_info): nodes.add(x.strip()) metadata_in_url['title_aux'] = title + + if preemptions is not None: + metadata['preemptions'] = preemptions + if node_pattern is not None: metadata_in_url['nodename_pattern'] = node_pattern + nodes = list(nodes) nodes.sort() data[git_url] = (nodes, metadata_in_url)