mirror of
https://github.com/Comfy-Org/ComfyUI-Manager.git
synced 2026-03-28 20:33:40 +08:00
Compare commits
59 Commits
71ecc7ac85
...
a4dbb86290
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4dbb86290 | ||
|
|
c8dce94c03 | ||
|
|
06496d07b3 | ||
|
|
a97f98c9cc | ||
|
|
8d0406f74f | ||
|
|
c64d14701d | ||
|
|
00332ae444 | ||
|
|
e8deb3d8fe | ||
|
|
8b234c99cf | ||
|
|
1f986d9c45 | ||
|
|
bacb8fb3cd | ||
|
|
e4a90089ab | ||
|
|
674b9f3705 | ||
|
|
4941fb8aa0 | ||
|
|
183af0dfa5 | ||
|
|
45ac5429f8 | ||
|
|
c771977a95 | ||
|
|
668d7bbb2c | ||
|
|
926cfabb58 | ||
|
|
a9a8d05115 | ||
|
|
e368f4366a | ||
|
|
dc5bddbc17 | ||
|
|
358a480408 | ||
|
|
c96fdb3c7a | ||
|
|
c090abcc02 | ||
|
|
1ff02be35f | ||
|
|
10fbfb88f7 | ||
|
|
9753df72ed | ||
|
|
095cc3f792 | ||
|
|
656171037b | ||
|
|
7ac10f9442 | ||
|
|
3925ba27b4 | ||
|
|
44ba79aa31 | ||
|
|
14d0e31268 | ||
|
|
033acffad1 | ||
|
|
d29ff808a5 | ||
|
|
dc9b6d655b | ||
|
|
d340c85013 | ||
|
|
e328353664 | ||
|
|
02785af8fd | ||
|
|
736ae5d63e | ||
|
|
e1eeb617d2 | ||
|
|
23b6c7f0de | ||
|
|
997f97e1fc | ||
|
|
ff335ff1a0 | ||
|
|
cb3036ef81 | ||
|
|
f762906188 | ||
|
|
dde7920f8c | ||
|
|
1a0d24110a | ||
|
|
e79f6c4471 | ||
|
|
a8a7024a84 | ||
|
|
1a56124af3 | ||
|
|
f7d56e62b9 | ||
|
|
f011bf5172 | ||
|
|
3c9c3196a1 | ||
|
|
8f0d16a7d8 | ||
|
|
ed1b1a446b | ||
|
|
3d0c41e1bc | ||
|
|
0979084230 |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
10136
github-stats.json
10136
github-stats.json
File diff suppressed because it is too large
Load Diff
@ -43,7 +43,7 @@ import manager_downloader
|
||||
from node_package import InstalledNodePackage
|
||||
|
||||
|
||||
version_code = [3, 37, 1]
|
||||
version_code = [3, 37, 2]
|
||||
version_str = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
|
||||
|
||||
|
||||
@ -2533,6 +2533,7 @@ def update_to_stable_comfyui(repo_path):
|
||||
else:
|
||||
logging.info(f"[ComfyUI-Manager] Updating ComfyUI: {current_tag} -> {latest_tag}")
|
||||
repo.git.checkout(latest_tag)
|
||||
execute_install_script("ComfyUI", repo_path, instant_execution=False, no_deps=False)
|
||||
return 'updated', latest_tag
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -169,6 +169,16 @@
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A fork of KJNodes for ComfyUI.\nVarious quality of life -nodes for ComfyUI, mostly just visual stuff to improve usability"
|
||||
},
|
||||
{
|
||||
"author": "huixingyun",
|
||||
"title": "ComfyUI-SoundFlow",
|
||||
"reference": "https://github.com/huixingyun/ComfyUI-SoundFlow",
|
||||
"files": [
|
||||
"https://github.com/huixingyun/ComfyUI-SoundFlow"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "forked from https://github.com/fredconex/ComfyUI-SoundFlow (removed)"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,5 +1,155 @@
|
||||
{
|
||||
"custom_nodes": [
|
||||
{
|
||||
"author": "PozzettiAndrea",
|
||||
"title": "ComfyUI-CameraAnalysis [REMOVED]",
|
||||
"reference": "https://github.com/PozzettiAndrea/ComfyUI-CameraAnalysis",
|
||||
"files": [
|
||||
"https://github.com/PozzettiAndrea/ComfyUI-CameraAnalysis"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Extracts camera intrinsic parameters from image EXIF data."
|
||||
},
|
||||
{
|
||||
"author": "fuzr0dah",
|
||||
"title": "comfyui-sceneassembly [REMOVED]",
|
||||
"reference": "https://github.com/fuzr0dah/comfyui-sceneassembly",
|
||||
"files": [
|
||||
"https://github.com/fuzr0dah/comfyui-sceneassembly"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A bunch of nodes I created that I also find useful."
|
||||
},
|
||||
{
|
||||
"author": "rslosch",
|
||||
"title": "ComfyUI-EZ_Prompts [REMOVED]",
|
||||
"reference": "https://github.com/rslosch/ComfyUI-EZ_Prompts",
|
||||
"files": [
|
||||
"https://github.com/rslosch/ComfyUI-EZ_Prompts"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A ComfyUI custom node extension that provides easy-to-use prompt templates and wildcards for AI image generation."
|
||||
},
|
||||
{
|
||||
"author": "hvppycoding",
|
||||
"title": "hvppyflow [REMOVED]",
|
||||
"reference": "https://github.com/hvppycoding/hvppyflow",
|
||||
"files": [
|
||||
"https://github.com/hvppycoding/hvppyflow"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI nodes for Automated Workflow"
|
||||
},
|
||||
{
|
||||
"author": "cedarconnor",
|
||||
"title": "ComfyUI-GEN3C-Gsplat [REMOVED]",
|
||||
"reference": "https://github.com/cedarconnor/ComfyUI-GEN3C-Gsplat",
|
||||
"files": [
|
||||
"https://github.com/cedarconnor/ComfyUI-GEN3C-Gsplat"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A custom ComfyUI node pack that bridges Cosmos/GEN3C video generation with in-graph Gaussian Splat (3DGS) training. It adds camera/trajectory tooling, dataset exporters, and two training backends (Nerfstudio CLI wrapper and an in-process gsplat optimizer) so artists can go from prompt to splat entirely inside ComfyUI.\nNOTE: The files in the repo are not organized."
|
||||
},
|
||||
{
|
||||
"author": "dowa-git",
|
||||
"title": "comfyui-dowa [REMOVED]",
|
||||
"reference": "https://github.com/dowa-git/comfyui-dowa",
|
||||
"files": [
|
||||
"https://github.com/dowa-git/comfyui-dowa"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Professional navigation bar widget for ComfyUI with JWT-based user authentication, workflow templates, and team collaboration features in a purple gradient design."
|
||||
},
|
||||
{
|
||||
"author": "Fablestarexpanse",
|
||||
"title": "Timer-Node-Comfyui [REMOVED]",
|
||||
"reference": "https://github.com/Fablestarexpanse/Timer-Node-Comfyui",
|
||||
"files": [
|
||||
"https://github.com/Fablestarexpanse/Timer-Node-Comfyui"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A custom ComfyUI node that displays live processing time in a red digital countdown clock format, perfect for monitoring image generation times and tracking performance between workflow nodes."
|
||||
},
|
||||
{
|
||||
"author": "cedarconnor",
|
||||
"title": "ComfyUI-OmniX [REMOVED]",
|
||||
"reference": "https://github.com/cedarconnor/ComfyUI-OmniX",
|
||||
"files": [
|
||||
"https://github.com/cedarconnor/ComfyUI-OmniX"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Extract comprehensive scene properties from 360-degree equirectangular panoramas, including depth, normals, and PBR materials, using OmniX adapters with Flux."
|
||||
},
|
||||
{
|
||||
"author": "cedarconnor",
|
||||
"title": "ComfyUI-DiT360 [REMOVED]",
|
||||
"reference": "https://github.com/cedarconnor/ComfyUI-DiT360",
|
||||
"files": [
|
||||
"https://github.com/cedarconnor/ComfyUI-DiT360"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Generate high-fidelity 360-degree panoramic images using the DiT360 diffusion transformer model in ComfyUI."
|
||||
},
|
||||
{
|
||||
"author": "PozzettiAndrea",
|
||||
"title": "ComfyUI-AnyTop [REMOVED]",
|
||||
"reference": "https://github.com/PozzettiAndrea/ComfyUI-AnyTop",
|
||||
"files": [
|
||||
"https://github.com/PozzettiAndrea/ComfyUI-AnyTop"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Standalone ComfyUI custom nodes for AnyTop - Universal Motion Generation for Any Skeleton Topology."
|
||||
},
|
||||
{
|
||||
"author": "penposs",
|
||||
"title": "ComfyUI-Banana-Node [REMOVED]",
|
||||
"reference": "https://github.com/penposs/ComfyUI-Banana-Node",
|
||||
"files": [
|
||||
"https://github.com/penposs/ComfyUI-Banana-Node"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A custom node for ComfyUI that generates images using Google’s Gemini 2.5 Flash Image Preview API."
|
||||
},
|
||||
{
|
||||
"author": "spiralmountain",
|
||||
"title": "ComfyUI_HDNodes [REMOVED]",
|
||||
"reference": "https://github.com/spiralmountain/ComfyUI_HDNodes",
|
||||
"files": [
|
||||
"https://github.com/spiralmountain/ComfyUI_HDNodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom nodes for ComfyUI that enable video generation using ByteDance's Seedance model via [a/Fal.ai](https://fal.ai/)."
|
||||
},
|
||||
{
|
||||
"author": "fredconex",
|
||||
"title": "Sync Edit [REMOVED]",
|
||||
"reference": "https://github.com/fredconex/ComfyUI-SyncEdit",
|
||||
"files": [
|
||||
"https://github.com/fredconex/ComfyUI-SyncEdit"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "This node allow to intercept changes on the input string and choose between use the current one or sync with incoming new one."
|
||||
},
|
||||
{
|
||||
"author": "fredconex",
|
||||
"title": "ComfyUI-SoundFlow [REMOVED]",
|
||||
"reference": "https://github.com/fredconex/ComfyUI-SoundFlow",
|
||||
"files": [
|
||||
"https://github.com/fredconex/ComfyUI-SoundFlow"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "This is a bunch of nodes for ComfyUI to help with sound work."
|
||||
},
|
||||
{
|
||||
"author": "fredconex",
|
||||
"title": "SongBloom [REMOVED]",
|
||||
"reference": "https://github.com/fredconex/ComfyUI-SongBloom",
|
||||
"files": [
|
||||
"https://github.com/fredconex/ComfyUI-SongBloom"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI Nodes for SongBloom"
|
||||
},
|
||||
{
|
||||
"author": "EQXai",
|
||||
"title": "ComfyUI_EQX [REMOVED]",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "comfyui-manager"
|
||||
description = "ComfyUI-Manager provides features to install and manage custom nodes for ComfyUI, as well as various functionalities to assist with ComfyUI."
|
||||
version = "3.37.1"
|
||||
version = "3.37.2"
|
||||
license = { file = "LICENSE.txt" }
|
||||
dependencies = ["GitPython", "PyGithub", "matrix-nio", "transformers", "huggingface-hub>0.20", "typer", "rich", "typing-extensions", "toml", "uv", "chardet"]
|
||||
|
||||
|
||||
132
scanner.py
132
scanner.py
@ -78,36 +78,14 @@ Examples:
|
||||
return args
|
||||
|
||||
|
||||
# Parse arguments
|
||||
args = parse_arguments()
|
||||
|
||||
# Determine mode
|
||||
scan_only_mode = args.scan_only is not None
|
||||
url_list_file = args.scan_only if scan_only_mode else None
|
||||
|
||||
# Determine temp_dir
|
||||
if args.temp_dir:
|
||||
temp_dir = args.temp_dir
|
||||
elif args.temp_dir_positional:
|
||||
temp_dir = args.temp_dir_positional
|
||||
else:
|
||||
temp_dir = os.path.join(os.getcwd(), ".tmp")
|
||||
|
||||
if not os.path.exists(temp_dir):
|
||||
os.makedirs(temp_dir)
|
||||
|
||||
# Determine skip flags
|
||||
skip_update = args.skip_update or args.skip_all
|
||||
skip_stat_update = args.skip_stat_update or args.skip_all or scan_only_mode
|
||||
|
||||
if not skip_stat_update:
|
||||
auth = Auth.Token(os.environ.get('GITHUB_TOKEN'))
|
||||
g = Github(auth=auth)
|
||||
else:
|
||||
g = None
|
||||
|
||||
|
||||
print(f"TEMP DIR: {temp_dir}")
|
||||
# Module-level variables (will be set in main if running as script)
|
||||
args = None
|
||||
scan_only_mode = False
|
||||
url_list_file = None
|
||||
temp_dir = None
|
||||
skip_update = False
|
||||
skip_stat_update = True
|
||||
g = None
|
||||
|
||||
|
||||
parse_cnt = 0
|
||||
@ -127,10 +105,17 @@ def extract_nodes(code_text):
|
||||
warnings.filterwarnings('ignore', category=DeprecationWarning)
|
||||
parsed_code = ast.parse(code_text)
|
||||
|
||||
assignments = (node for node in parsed_code.body if isinstance(node, ast.Assign))
|
||||
# Support both ast.Assign and ast.AnnAssign (for type-annotated assignments)
|
||||
assignments = (node for node in parsed_code.body if isinstance(node, (ast.Assign, ast.AnnAssign)))
|
||||
|
||||
for assignment in assignments:
|
||||
if isinstance(assignment.targets[0], ast.Name) and assignment.targets[0].id in ['NODE_CONFIG', 'NODE_CLASS_MAPPINGS']:
|
||||
# Handle ast.AnnAssign (e.g., NODE_CLASS_MAPPINGS: Type = {...})
|
||||
if isinstance(assignment, ast.AnnAssign):
|
||||
if isinstance(assignment.target, ast.Name) and assignment.target.id in ['NODE_CONFIG', 'NODE_CLASS_MAPPINGS']:
|
||||
node_class_mappings = assignment.value
|
||||
break
|
||||
# Handle ast.Assign (e.g., NODE_CLASS_MAPPINGS = {...})
|
||||
elif isinstance(assignment.targets[0], ast.Name) and assignment.targets[0].id in ['NODE_CONFIG', 'NODE_CLASS_MAPPINGS']:
|
||||
node_class_mappings = assignment.value
|
||||
break
|
||||
else:
|
||||
@ -250,7 +235,8 @@ def scan_in_file(filename, is_builtin=False):
|
||||
with open(filename, encoding='utf-8', errors='ignore') as file:
|
||||
code = file.read()
|
||||
|
||||
pattern = r"_CLASS_MAPPINGS\s*=\s*{([^}]*)}"
|
||||
# Support type annotations (e.g., NODE_CLASS_MAPPINGS: Type = {...}) and line continuations (\)
|
||||
pattern = r"_CLASS_MAPPINGS\s*(?::\s*\w+\s*)?=\s*(?:\\\s*)?{([^}]*)}"
|
||||
regex = re.compile(pattern, re.MULTILINE | re.DOTALL)
|
||||
|
||||
nodes = set()
|
||||
@ -482,21 +468,21 @@ def update_custom_nodes(scan_only_mode=False, url_list_file=None):
|
||||
raise ValueError("url_list_file is required in scan-only mode")
|
||||
|
||||
git_url_titles_preemptions = get_urls_from_list_file(url_list_file)
|
||||
print(f"\n[Scan-Only Mode]")
|
||||
print("\n[Scan-Only Mode]")
|
||||
print(f" - URL source: {url_list_file}")
|
||||
print(f" - GitHub stats: DISABLED")
|
||||
print(" - GitHub stats: DISABLED")
|
||||
print(f" - Git clone/pull: {'ENABLED' if not skip_update else 'DISABLED'}")
|
||||
print(f" - Metadata: EMPTY")
|
||||
print(" - Metadata: EMPTY")
|
||||
else:
|
||||
if not os.path.exists('custom-node-list.json'):
|
||||
raise FileNotFoundError("custom-node-list.json not found")
|
||||
|
||||
git_url_titles_preemptions = get_git_urls_from_json('custom-node-list.json')
|
||||
print(f"\n[Standard Mode]")
|
||||
print(f" - URL source: custom-node-list.json")
|
||||
print("\n[Standard Mode]")
|
||||
print(" - URL source: custom-node-list.json")
|
||||
print(f" - GitHub stats: {'ENABLED' if not skip_stat_update else 'DISABLED'}")
|
||||
print(f" - Git clone/pull: {'ENABLED' if not skip_update else 'DISABLED'}")
|
||||
print(f" - Metadata: FULL")
|
||||
print(" - Metadata: FULL")
|
||||
|
||||
def process_git_url_title(url, title, preemptions, node_pattern):
|
||||
name = os.path.basename(url)
|
||||
@ -689,7 +675,14 @@ def gen_json(node_info, scan_only_mode=False):
|
||||
|
||||
data[git_url] = (nodes, metadata)
|
||||
else:
|
||||
print(f"WARN: {dirname} is removed from custom-node-list.json")
|
||||
# Scan-only mode: Repository not in node_info (expected behavior)
|
||||
# Construct URL from dirname (author_repo format)
|
||||
if '_' in dirname:
|
||||
parts = dirname.split('_', 1)
|
||||
git_url = f"https://github.com/{parts[0]}/{parts[1]}"
|
||||
data[git_url] = (nodes, metadata)
|
||||
else:
|
||||
print(f"WARN: {dirname} is removed from custom-node-list.json")
|
||||
|
||||
for file in node_files:
|
||||
nodes, metadata = scan_in_file(file)
|
||||
@ -775,24 +768,53 @@ def gen_json(node_info, scan_only_mode=False):
|
||||
json.dump(data, file, indent=4, sort_keys=True)
|
||||
|
||||
|
||||
print("### ComfyUI Manager Node Scanner ###")
|
||||
if __name__ == "__main__":
|
||||
# Parse arguments
|
||||
args = parse_arguments()
|
||||
|
||||
if scan_only_mode:
|
||||
print(f"\n# [Scan-Only Mode] Processing URL list: {url_list_file}\n")
|
||||
else:
|
||||
print("\n# [Standard Mode] Updating extensions\n")
|
||||
# Determine mode
|
||||
scan_only_mode = args.scan_only is not None
|
||||
url_list_file = args.scan_only if scan_only_mode else None
|
||||
|
||||
# Update/clone repositories and collect node info
|
||||
updated_node_info = update_custom_nodes(scan_only_mode, url_list_file)
|
||||
# Determine temp_dir
|
||||
if args.temp_dir:
|
||||
temp_dir = args.temp_dir
|
||||
elif args.temp_dir_positional:
|
||||
temp_dir = args.temp_dir_positional
|
||||
else:
|
||||
temp_dir = os.path.join(os.getcwd(), ".tmp")
|
||||
|
||||
print("\n# Generating 'extension-node-map.json'...\n")
|
||||
if not os.path.exists(temp_dir):
|
||||
os.makedirs(temp_dir)
|
||||
|
||||
# Generate extension-node-map.json
|
||||
gen_json(updated_node_info, scan_only_mode)
|
||||
# Determine skip flags
|
||||
skip_update = args.skip_update or args.skip_all
|
||||
skip_stat_update = args.skip_stat_update or args.skip_all or scan_only_mode
|
||||
|
||||
print("\n✅ DONE.\n")
|
||||
if not skip_stat_update:
|
||||
auth = Auth.Token(os.environ.get('GITHUB_TOKEN'))
|
||||
g = Github(auth=auth)
|
||||
else:
|
||||
g = None
|
||||
|
||||
if scan_only_mode:
|
||||
print("Output: extension-node-map.json (node mappings only)")
|
||||
else:
|
||||
print("Output: extension-node-map.json (full metadata)")
|
||||
print("### ComfyUI Manager Node Scanner ###")
|
||||
|
||||
if scan_only_mode:
|
||||
print(f"\n# [Scan-Only Mode] Processing URL list: {url_list_file}\n")
|
||||
else:
|
||||
print("\n# [Standard Mode] Updating extensions\n")
|
||||
|
||||
# Update/clone repositories and collect node info
|
||||
updated_node_info = update_custom_nodes(scan_only_mode, url_list_file)
|
||||
|
||||
print("\n# Generating 'extension-node-map.json'...\n")
|
||||
|
||||
# Generate extension-node-map.json
|
||||
gen_json(updated_node_info, scan_only_mode)
|
||||
|
||||
print("\n✅ DONE.\n")
|
||||
|
||||
if scan_only_mode:
|
||||
print("Output: extension-node-map.json (node mappings only)")
|
||||
else:
|
||||
print("Output: extension-node-map.json (full metadata)")
|
||||
Loading…
Reference in New Issue
Block a user