mirror of
https://github.com/Comfy-Org/ComfyUI-Manager.git
synced 2026-01-11 06:30:48 +08:00
Compare commits
172 Commits
d31b71b584
...
21b62d6299
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21b62d6299 | ||
|
|
969e08bd34 | ||
|
|
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 | ||
|
|
d93d002da0 | ||
|
|
baaa0479e8 | ||
|
|
cc3bd7a056 | ||
|
|
4ecefb3b71 | ||
|
|
f24b5aa251 | ||
|
|
de547da4cd | ||
|
|
0f884166a6 | ||
|
|
63379f759d | ||
|
|
8fdff20243 | ||
|
|
5dfa07ca03 | ||
|
|
343645be6a | ||
|
|
91bf21d7a8 | ||
|
|
be6516cfd3 | ||
|
|
61f1e516a3 | ||
|
|
73b2278b45 | ||
|
|
aa625e30b6 | ||
|
|
29a46fe4ce | ||
|
|
5b3ee49530 | ||
|
|
a9158a101f | ||
|
|
feed8abb34 | ||
|
|
70decc740f | ||
|
|
5b5c83f8c5 | ||
|
|
773c06f40d | ||
|
|
737e6ad5ed | ||
|
|
81bca9c94e | ||
|
|
eef0654de2 | ||
|
|
997a00b8a2 | ||
|
|
4d25232c5f | ||
|
|
135befa101 | ||
|
|
44cac3fc43 | ||
|
|
449fa3510e | ||
|
|
d958af8aad | ||
|
|
09f8d5cb2d | ||
|
|
aedc99cefd | ||
|
|
b32cab6e9a | ||
|
|
a95186965e | ||
|
|
7067de1bb2 | ||
|
|
f45d878d21 | ||
|
|
a0532b938d | ||
|
|
6ad12b7652 | ||
|
|
02887c6c9b | ||
|
|
1b645e1cc3 | ||
|
|
0a4b2a0488 | ||
|
|
d4ce6ddc52 | ||
|
|
5a5b989533 | ||
|
|
b57cffb0fa | ||
|
|
72aa95cacf | ||
|
|
14ef448937 | ||
|
|
1c10607c06 | ||
|
|
41e53a1f2a | ||
|
|
cde83e9a38 | ||
|
|
6c206b1c72 | ||
|
|
a474219e7b | ||
|
|
3b8d25eb31 | ||
|
|
0faa0aa668 | ||
|
|
0fcdcc93a2 | ||
|
|
461d5e72fe | ||
|
|
3f030a2121 | ||
|
|
7fb8e8662f | ||
|
|
dd3ab9cff2 | ||
|
|
97b518de12 | ||
|
|
d2a795c866 | ||
|
|
8a3d65be20 | ||
|
|
b2126d8ba5 | ||
|
|
6386411d21 | ||
|
|
4250244136 | ||
|
|
77c4f9993d | ||
|
|
c7c8417577 | ||
|
|
9d0985ded8 | ||
|
|
3663e10e33 | ||
|
|
5f37a82c3c | ||
|
|
026bf1dfd7 | ||
|
|
643a6e5080 | ||
|
|
5267502896 | ||
|
|
c3c152122d | ||
|
|
afeac097e5 | ||
|
|
e5cea64132 | ||
|
|
26da78cf15 | ||
|
|
179a1e1ca0 | ||
|
|
b379d275d1 | ||
|
|
133cdfb203 | ||
|
|
2b79edd9be | ||
|
|
3862a92e04 | ||
|
|
f4e3817fcc | ||
|
|
61f0f5d67c | ||
|
|
87f57551ea | ||
|
|
ee51efed69 | ||
|
|
5dab865681 | ||
|
|
8c0581eebc | ||
|
|
a72f9f422c | ||
|
|
1354a8c970 | ||
|
|
00a5115267 | ||
|
|
00282eab7b | ||
|
|
bec128de58 | ||
|
|
9edfa7b4fa | ||
|
|
a9af70e5f0 | ||
|
|
910caf593f | ||
|
|
02dc072dc7 | ||
|
|
78fb354452 | ||
|
|
66f5eca7fa | ||
|
|
be95396a57 | ||
|
|
59cbed429f | ||
|
|
d49df7aebb | ||
|
|
0aa9faad2e | ||
|
|
1337def888 | ||
|
|
4b100c558b | ||
|
|
1425a71ece | ||
|
|
a8524508fe | ||
|
|
a5ff973d53 | ||
|
|
337c9aa2c7 | ||
|
|
f1448403ac | ||
|
|
d0b5f77ec6 | ||
|
|
9cb22ffb60 | ||
|
|
f556962d82 | ||
|
|
d28448d519 | ||
|
|
c590a88ffd | ||
|
|
a1fc6c817b | ||
|
|
5554e52799 | ||
|
|
ca749eb4d2 | ||
|
|
41ceee3d24 | ||
|
|
5acfd52986 | ||
|
|
ec4c7b2f6a | ||
|
|
22a3d8f95f | ||
|
|
06b89ca277 | ||
|
|
9e5ffbd00a | ||
|
|
39e92ed778 | ||
|
|
68a3ec567a | ||
|
|
28231e81b3 | ||
|
|
b2ee0feeaa | ||
|
|
5541b6b366 | ||
|
|
408a5fe27e | ||
|
|
bffc73f976 | ||
|
|
bd6edfc9dd | ||
|
|
2cb24e8a94 | ||
|
|
a49779c4d2 | ||
|
|
15a5a5f5df | ||
|
|
b5e0558d6e | ||
|
|
4d683b23fc | ||
|
|
c13da606b2 | ||
|
|
f69183436a |
4
check.sh
4
check.sh
@ -37,7 +37,7 @@ find ~/.tmp/default -name "*.py" -print0 | xargs -0 grep -E "crypto|^_A="
|
||||
|
||||
echo
|
||||
echo CHECK3
|
||||
find ~/.tmp/default -name "requirements.txt" | xargs grep "^\s*https\\?:"
|
||||
find ~/.tmp/default -name "requirements.txt" | xargs grep "\.whl"
|
||||
find ~/.tmp/default -name "requirements.txt" | xargs grep "^\s*[^#]*https\?:"
|
||||
find ~/.tmp/default -name "requirements.txt" | xargs grep "^\s*[^#].*\.whl"
|
||||
|
||||
echo
|
||||
|
||||
3408
custom-node-list.json
Executable file → Normal file
3408
custom-node-list.json
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
11970
github-stats.json
11970
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]
|
||||
version_code = [3, 37, 1]
|
||||
version_str = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
|
||||
|
||||
|
||||
@ -2664,9 +2664,13 @@ def check_state_of_git_node_pack_single(item, do_fetch=False, do_update_check=Tr
|
||||
|
||||
|
||||
def get_installed_pip_packages():
|
||||
# extract pip package infos
|
||||
cmd = manager_util.make_pip_cmd(['freeze'])
|
||||
pips = subprocess.check_output(cmd, text=True).split('\n')
|
||||
try:
|
||||
# extract pip package infos
|
||||
cmd = manager_util.make_pip_cmd(['freeze'])
|
||||
pips = subprocess.check_output(cmd, text=True).split('\n')
|
||||
except Exception as e:
|
||||
logging.warning("[ComfyUI-Manager] Could not enumerate pip packages for snapshot: %s", e)
|
||||
return {}
|
||||
|
||||
res = {}
|
||||
for x in pips:
|
||||
|
||||
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,389 @@
|
||||
{
|
||||
"custom_nodes": [
|
||||
{
|
||||
"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]",
|
||||
"reference": "https://github.com/EQXai/ComfyUI_EQX",
|
||||
"files": [
|
||||
"https://github.com/EQXai/ComfyUI_EQX"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "NODES: SaveImage_EQX, File Image Selector, Load Prompt From File - EQX, LoraStackEQX_random, Extract Filename - EQX, Extract LORA name - EQX, NSFW Detector EQX, NSFW Detector Advanced EQX"
|
||||
},
|
||||
{
|
||||
"author": "wizdroid",
|
||||
"title": "Wizdroid ComfyUI Outfit Selection [REMOVED]",
|
||||
"reference": "https://github.com/wizdroid/wizdroid-fashionista",
|
||||
"files": [
|
||||
"https://github.com/wizdroid/wizdroid-fashionista"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A comprehensive outfit generation system for ComfyUI with AI-powered prompt enhancement and dynamic outfit composition."
|
||||
},
|
||||
{
|
||||
"author": "enternalsaga",
|
||||
"title": "NBA-ComfyUINode [REMOVED]",
|
||||
"reference": "https://github.com/enternalsaga/NBA-ComfyUINode-public",
|
||||
"files": [
|
||||
"https://github.com/enternalsaga/NBA-ComfyUINode-public"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Version 1.2.1 - Dependency cleanup and archived LineSelector node\nA comprehensive collection of custom nodes for ComfyUI, providing advanced image processing, workflow control, and utility functions to enhance your AI image generation workflows."
|
||||
},
|
||||
{
|
||||
"author": "sselpah",
|
||||
"title": "ComfyUI-sselpah-nodes [REMOVED]",
|
||||
"reference": "https://github.com/sselpah/ComfyUI-sselpah-nodes",
|
||||
"files": [
|
||||
"https://github.com/sselpah/ComfyUI-sselpah-nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Extension of IPAdapter implementation by cubiq and whoever contributed to that repository"
|
||||
},
|
||||
{
|
||||
"author": "vsaan212",
|
||||
"title": "ComfyUI Text Split Node [REMOVED]",
|
||||
"reference": "https://github.com/vsaan212/Comfy-ui-textsplit",
|
||||
"files": [
|
||||
"https://github.com/vsaan212/Comfy-ui-textsplit"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A custom ComfyUI node that splits text into multiple outputs for feeding complex multi-scene renders. This node allows you to dynamically control the number of splits and use custom separators."
|
||||
},
|
||||
{
|
||||
"author": "EnragedAntelope",
|
||||
"title": "ComfyUI-Doubutsu-Describer [DEPRECATED]",
|
||||
"reference": "https://github.com/EnragedAntelope/ComfyUI-Doubutsu-Describer",
|
||||
"files": [
|
||||
"https://github.com/EnragedAntelope/ComfyUI-Doubutsu-Describer"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "This custom node for ComfyUI allows you to use the Doubutsu small VLM model to describe images. Credit and further information on Doubutsu: [a/https://huggingface.co/qresearch/doubutsu-2b-pt-756](https://huggingface.co/qresearch/doubutsu-2b-pt-756)"
|
||||
},
|
||||
{
|
||||
"author": "vsaan212",
|
||||
"title": "ComfyUI Subject Selector [DEPRECATED]",
|
||||
"reference": "https://github.com/vsaan212/ComfyUI_subjectselector",
|
||||
"files": [
|
||||
"https://github.com/vsaan212/ComfyUI_subjectselector"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI_subjectselector is a custom ComfyUI node that allows you to manage and select text-based subject descriptions directly from the workflow UI. This node was designed to pair seamlessly with [a/ComfyUI-textsplit](https://github.com/vsaan212/Comfy-ui-textsplit), providing a clean, modular way to feed descriptive text prompts into your generation pipeline."
|
||||
},
|
||||
{
|
||||
"author": "agxagi",
|
||||
"title": "Autoregressive Transformer and Rolling Diffusion Sampler for ComfyUI [REMOVED]",
|
||||
"reference": "https://github.com/agxagi/ComfyUI-GPT4o-Image-Gen-FLUX-DEV",
|
||||
"files": [
|
||||
"https://github.com/agxagi/ComfyUI-GPT4o-Image-Gen-FLUX-DEV"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A custom ComfyUI node that implements an Autoregressive Transformer and Rolling Diffusion-like Decoder using Black Forest Lab's Flux-Dev model for accurate text-to-image generation, similar to GPT-4o's image generation approach.\nNOTE: The files in the repo are not organized."
|
||||
},
|
||||
{
|
||||
"author": "walke2019",
|
||||
"title": "ComfyUI-GGUF-VisionLM [REMOVED]",
|
||||
"reference": "https://github.com/walke2019/ComfyUI-GGUF-VisionLM",
|
||||
"files": [
|
||||
"https://github.com/walke2019/ComfyUI-GGUF-VisionLM"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI nodes for running GGUF quantized Qwen2.5-VL models using llama.cpp"
|
||||
},
|
||||
{
|
||||
"author": "neocrz",
|
||||
"title": "comfyui-tinyae [REMOVED]",
|
||||
"reference": "https://github.com/neocrz/comfyui-tinyae",
|
||||
"files": [
|
||||
"https://github.com/neocrz/comfyui-tinyae"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "NODES: TinyAE Encode (Image/Video), TinyAE Decode (Image/Video), TinyAE Encode Tiled (Image), TinyAE Decode Tiled (Image)"
|
||||
},
|
||||
{
|
||||
"author": "Laser-one",
|
||||
"title": "ComfyUI-align-pose [REMOVED]",
|
||||
"reference": "https://github.com/Laser-one/ComfyUI-align-pose",
|
||||
"files": [
|
||||
"https://github.com/Laser-one/ComfyUI-align-pose"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "NODES:align pose"
|
||||
},
|
||||
{
|
||||
"author": "nomadoor",
|
||||
"title": "ComfyUI Video Stabilizer",
|
||||
"reference": "https://github.com/nomadoor/ComfyUI-Video-Stabilizer",
|
||||
"files": [
|
||||
"https://github.com/nomadoor/ComfyUI-Video-Stabilizer"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Two complementary stabiliser nodes for ComfyUI: Video Stabilizer (Classic), Video Stabilizer (Flow)"
|
||||
},
|
||||
{
|
||||
"author": "0xhappydev",
|
||||
"title": "comfyui-qwen-image-tools",
|
||||
"reference": "https://github.com/0xhappydev/comfyui-qwen-image-tools",
|
||||
"files": [
|
||||
"https://github.com/0xhappydev/comfyui-qwen-image-tools"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom nodes for Qwen-Image-Edit with multi-image support, more flexibility around the vision transformer (qwen2.5-vl), custom system prompts, and some other experimental things to come."
|
||||
},
|
||||
{
|
||||
"author": "Rathius-Saranoth",
|
||||
"title": "Rathius ComfyUI Nodes",
|
||||
"reference": "https://github.com/Rathius-Saranoth/rathius-comfyui-nodes",
|
||||
"files": [
|
||||
"https://github.com/Rathius-Saranoth/rathius-comfyui-nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom nodes for ComfyUI by Rathius"
|
||||
},
|
||||
{
|
||||
"author": "Hiero207",
|
||||
"title": "Hiero-Nodes [REMOVED]",
|
||||
"id": "hiero",
|
||||
"reference": "https://github.com/Hiero207/ComfyUI-Hiero-Nodes",
|
||||
"files": [
|
||||
"https://github.com/Hiero207/ComfyUI-Hiero-Nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Nodes:Post to Discord w/ Webhook"
|
||||
},
|
||||
{
|
||||
"author": "NeoDroleDeGueule",
|
||||
"title": "comfyui-image-mixer",
|
||||
"reference": "https://github.com/NeoDroleDeGueule/comfyui-image-mixer [REMOVED]",
|
||||
"files": [
|
||||
"https://github.com/NeoDroleDeGueule/comfyui-image-mixer"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A ComfyUI custom node that blends two images in latent space using a mix factor slider."
|
||||
},
|
||||
{
|
||||
"author": "Glarus-akash",
|
||||
"title": "ComfyUI_Image_Upscaler [REMOVED]",
|
||||
"reference": "https://github.com/Glarus-akash/ComfyUI_Image_Upscaler",
|
||||
"files": [
|
||||
"https://github.com/Glarus-akash/ComfyUI_Image_Upscaler"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Welcome to the Image Upscaler & Restorer project! This tool utilizes the [a/GFPGAN](https://github.com/TencentARC/GFPGAN) algorithm to enhance and restore images, providing a seamless way to improve image quality."
|
||||
},
|
||||
{
|
||||
"author": "styletransfer",
|
||||
"title": "Sequential Group Controller for ComfyUI [REMOVED]",
|
||||
"reference": "https://github.com/styletransfer/ComfyUI_SequentialGroupController",
|
||||
"files": [
|
||||
"https://github.com/styletransfer/ComfyUI_SequentialGroupController"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Control which groups execute based on iteration ranges - a simplified alternative to complex conditional branching workflows."
|
||||
},
|
||||
{
|
||||
"author": "xl0",
|
||||
"title": "q_tools [REMOVED]",
|
||||
"reference": "https://github.com/xl0/q_tools",
|
||||
"files": [
|
||||
"https://github.com/xl0/q_tools"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "NODES: QLoadLatent, QLinearScheduler, QPreviewLatent, QGaussianLatent, QUniformLatent, QKSampler"
|
||||
},
|
||||
{
|
||||
"author": "tmode-1960",
|
||||
"title": "comfyui-ta-nodes-pack [REMOVED]",
|
||||
"reference": "https://github.com/tmode-1960/comfyui-ta-nodes-pack",
|
||||
"files": [
|
||||
"https://github.com/tmode-1960/comfyui-ta-nodes-pack"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Model loaders with an additional model name output"
|
||||
},
|
||||
{
|
||||
"author": "Shadetail",
|
||||
"title": "Eagleshadow Custom Nodes [REMOVED]",
|
||||
"id": "eagleshadow",
|
||||
"reference": "https://github.com/Shadetail/ComfyUI_Eagleshadow",
|
||||
"files": [
|
||||
"https://github.com/Shadetail/ComfyUI_Eagleshadow"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom nodes for ComfyUI by Eagleshadow."
|
||||
},
|
||||
{
|
||||
"author": "manycore-maas",
|
||||
"title": "ComfyUI-SpatialGen [REMOVED]",
|
||||
"reference": "https://github.com/manycore-maas/ComfyUI-SpatialGen",
|
||||
"files": [
|
||||
"https://github.com/manycore-maas/ComfyUI-SpatialGen"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Scene Viewer of SpatialGen"
|
||||
},
|
||||
{
|
||||
"author": "YinBailiang",
|
||||
"title": "MergeBlockWeighted_fo_ComfyUI [REMOVED]",
|
||||
"id": "mergeblockweighted_fo_comfyui",
|
||||
"reference": "https://github.com/YinBailiang/MergeBlockWeighted_fo_ComfyUI",
|
||||
"files": [
|
||||
"https://github.com/YinBailiang/MergeBlockWeighted_fo_ComfyUI"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Nodes: MergeBlockWeighted"
|
||||
},
|
||||
{
|
||||
"author": "facok",
|
||||
"title": "ComfyUI-FokToolset [REMOVED]",
|
||||
"reference": "https://github.com/facok/ComfyUI-FokToolset",
|
||||
"files": [
|
||||
"https://github.com/facok/ComfyUI-FokToolset"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "NODES: Fok Preprocess Ref Image (Phantom)"
|
||||
},
|
||||
{
|
||||
"author": "Elawphant",
|
||||
"title": "ComfyUI-MusicGen [WIP]",
|
||||
"id": "musicgen",
|
||||
"reference": "https://github.com/Elawphant/ComfyUI-MusicGen",
|
||||
"files": [
|
||||
"https://github.com/Elawphant/ComfyUI-MusicGen"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI for Meta MusicGen."
|
||||
},
|
||||
{
|
||||
"author": "isaac-mcfadyen",
|
||||
"title": "ComfyUI-QwenClip [REMOVED]",
|
||||
"reference": "https://github.com/isaac-mcfadyen/ComfyUI-QwenClip",
|
||||
"files": [
|
||||
"https://github.com/isaac-mcfadyen/ComfyUI-QwenClip"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A variety of random text encoder tools intended for use with ComfyUI and Qwen Image/Qwen Image Edit. More (may) be added as I try out various modifications to Qwen Image."
|
||||
},
|
||||
{
|
||||
"author": "Gaotian",
|
||||
"title": "KLComfyUI-Nodes [REMOVED]",
|
||||
"reference": "https://github.com/Gaotian-cpu/KLComfyUI-Nodes",
|
||||
"files": [
|
||||
"https://github.com/Gaotian-cpu/KLComfyUI-Nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "NODES: Single Video_Img Callback"
|
||||
},
|
||||
{
|
||||
"author": "geltz",
|
||||
"title": "Momentum Guidance for ComfyUI [REMOVED]",
|
||||
"reference": "https://github.com/geltz/ComfyUI-MomentumGuidance",
|
||||
"files": [
|
||||
"https://github.com/geltz/ComfyUI-MomentumGuidance"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Momentum Guidance (MG) is a training-free guidance method that reduces computational cost by 40% compared to standard guidance techniques like CFG or PAG."
|
||||
},
|
||||
{
|
||||
"author": "GeekyGhost",
|
||||
"title": "Studio42 Image, Audio, and Video Editing Suite for ComfyUI [REMOVED]",
|
||||
"reference": "https://github.com/GeekyGhost/24oiduts-ComfyUI",
|
||||
"files": [
|
||||
"https://github.com/GeekyGhost/24oiduts-ComfyUI"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Studio42 is a comprehensive suite of advanced custom nodes that brings professional-grade image and video editing capabilities to ComfyUI. Designed for efficiency, quality, and creative flexibility, this suite provides cutting-edge background removal, layer composition, and patch manipulation tools used in modern VFX and content creation workflows."
|
||||
},
|
||||
{
|
||||
"author": "rvage",
|
||||
"title": "ComfyUI-RvTools-X [REMOVED]",
|
||||
"reference": "https://github.com/r-vage/ComfyUI-RvTools-X",
|
||||
"files": [
|
||||
"https://github.com/r-vage/ComfyUI-RvTools-X"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI custom nodes and utilities for workflow building, type conversions, checkpoint/pipe loaders and file utilities."
|
||||
},
|
||||
{
|
||||
"author": "heyburns",
|
||||
"title": "LinxUtil [REMOVED]",
|
||||
"reference": "https://github.com/heyburns/LinxUtil",
|
||||
"files": [
|
||||
"https://github.com/heyburns/LinxUtil"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Utility nodes for ComfyUI. Created solely for my own use case, shared as a courtesy only.\nNOTE: The files in the repo are not organized."
|
||||
},
|
||||
{
|
||||
"author": "fcanfora",
|
||||
"title": "comfyui-camera-tools [REMOVED]",
|
||||
"reference": "https://github.com/fcanfora/comfyui-camera-tools",
|
||||
"files": [
|
||||
"https://github.com/fcanfora/comfyui-camera-tools"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "NODES: Load Camera From File, Load 3D, Load 3D - Animation, Preview 3D, Preview 3D - Animation"
|
||||
},
|
||||
{
|
||||
"author": "ziwang-com",
|
||||
"title": "comfyui-deepseek-r1 [REMOVED]",
|
||||
@ -923,16 +1307,6 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "This node provides advanced text-to-speech functionality powered by KokoroTTS. Follow the instructions below to install, configure, and use the node within your portable ComfyUI installation."
|
||||
},
|
||||
{
|
||||
"author": "MushroomFleet",
|
||||
"title": "DJZ-Pedalboard [REMOVED]",
|
||||
"reference": "https://github.com/MushroomFleet/DJZ-Pedalboard",
|
||||
"files": [
|
||||
"https://github.com/MushroomFleet/DJZ-Pedalboard"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "This project provides a collection of custom nodes designed for enhanced audio effects in ComfyUI. With an intuitive pedalboard interface, users can easily integrate and manipulate various audio effects within their workflows."
|
||||
},
|
||||
{
|
||||
"author": "MushroomFleet",
|
||||
"title": "SVG Suite for ComfyUI [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"
|
||||
version = "3.37.1"
|
||||
license = { file = "LICENSE.txt" }
|
||||
dependencies = ["GitPython", "PyGithub", "matrix-nio", "transformers", "huggingface-hub>0.20", "typer", "rich", "typing-extensions", "toml", "uv", "chardet"]
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ GitPython
|
||||
PyGithub
|
||||
matrix-nio
|
||||
transformers
|
||||
huggingface-hub>0.20
|
||||
huggingface-hub
|
||||
typer
|
||||
rich
|
||||
typing-extensions
|
||||
|
||||
403
scanner.py
403
scanner.py
@ -7,6 +7,8 @@ import concurrent
|
||||
import datetime
|
||||
import concurrent.futures
|
||||
import requests
|
||||
import warnings
|
||||
import argparse
|
||||
|
||||
builtin_nodes = set()
|
||||
|
||||
@ -39,27 +41,51 @@ def download_url(url, dest_folder, filename=None):
|
||||
raise Exception(f"Failed to download file from {url}")
|
||||
|
||||
|
||||
# prepare temp dir
|
||||
if len(sys.argv) > 1:
|
||||
temp_dir = sys.argv[1]
|
||||
else:
|
||||
temp_dir = os.path.join(os.getcwd(), ".tmp")
|
||||
def parse_arguments():
|
||||
"""Parse command-line arguments"""
|
||||
parser = argparse.ArgumentParser(
|
||||
description='ComfyUI Manager Node Scanner',
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog='''
|
||||
Examples:
|
||||
# Standard mode
|
||||
python3 scanner.py
|
||||
python3 scanner.py --skip-update
|
||||
|
||||
if not os.path.exists(temp_dir):
|
||||
os.makedirs(temp_dir)
|
||||
# Scan-only mode
|
||||
python3 scanner.py --scan-only temp-urls-clean.list
|
||||
python3 scanner.py --scan-only urls.list --temp-dir /custom/temp
|
||||
python3 scanner.py --scan-only urls.list --skip-update
|
||||
'''
|
||||
)
|
||||
|
||||
parser.add_argument('--scan-only', type=str, metavar='URL_LIST_FILE',
|
||||
help='Scan-only mode: provide URL list file (one URL per line)')
|
||||
parser.add_argument('--temp-dir', type=str, metavar='DIR',
|
||||
help='Temporary directory for cloned repositories')
|
||||
parser.add_argument('--skip-update', action='store_true',
|
||||
help='Skip git clone/pull operations')
|
||||
parser.add_argument('--skip-stat-update', action='store_true',
|
||||
help='Skip GitHub stats collection')
|
||||
parser.add_argument('--skip-all', action='store_true',
|
||||
help='Skip all update operations')
|
||||
|
||||
# Backward compatibility: positional argument for temp_dir
|
||||
parser.add_argument('temp_dir_positional', nargs='?', metavar='TEMP_DIR',
|
||||
help='(Legacy) Temporary directory path')
|
||||
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
|
||||
skip_update = '--skip-update' in sys.argv or '--skip-all' in sys.argv
|
||||
skip_stat_update = '--skip-stat-update' in sys.argv or '--skip-all' in sys.argv
|
||||
|
||||
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
|
||||
@ -74,10 +100,13 @@ def extract_nodes(code_text):
|
||||
parse_cnt += 1
|
||||
|
||||
code_text = re.sub(r'\\[^"\']', '', code_text)
|
||||
parsed_code = ast.parse(code_text)
|
||||
with warnings.catch_warnings():
|
||||
warnings.filterwarnings('ignore', category=SyntaxWarning)
|
||||
warnings.filterwarnings('ignore', category=DeprecationWarning)
|
||||
parsed_code = ast.parse(code_text)
|
||||
|
||||
assignments = (node for node in parsed_code.body if isinstance(node, ast.Assign))
|
||||
|
||||
|
||||
for assignment in assignments:
|
||||
if isinstance(assignment.targets[0], ast.Name) and assignment.targets[0].id in ['NODE_CONFIG', 'NODE_CLASS_MAPPINGS']:
|
||||
node_class_mappings = assignment.value
|
||||
@ -91,7 +120,7 @@ def extract_nodes(code_text):
|
||||
for key in node_class_mappings.keys:
|
||||
if key is not None and isinstance(key.value, str):
|
||||
s.add(key.value.strip())
|
||||
|
||||
|
||||
return s
|
||||
else:
|
||||
return set()
|
||||
@ -99,6 +128,99 @@ def extract_nodes(code_text):
|
||||
return set()
|
||||
|
||||
|
||||
def has_comfy_node_base(class_node):
|
||||
"""Check if class inherits from io.ComfyNode or ComfyNode"""
|
||||
for base in class_node.bases:
|
||||
# Case 1: ComfyNode
|
||||
if isinstance(base, ast.Name) and base.id == 'ComfyNode':
|
||||
return True
|
||||
# Case 2: io.ComfyNode
|
||||
elif isinstance(base, ast.Attribute):
|
||||
if base.attr == 'ComfyNode':
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def extract_keyword_value(call_node, keyword):
|
||||
"""
|
||||
Extract string value of keyword argument
|
||||
Schema(node_id="MyNode") -> "MyNode"
|
||||
"""
|
||||
for kw in call_node.keywords:
|
||||
if kw.arg == keyword:
|
||||
# ast.Constant (Python 3.8+)
|
||||
if isinstance(kw.value, ast.Constant):
|
||||
if isinstance(kw.value.value, str):
|
||||
return kw.value.value
|
||||
# ast.Str (Python 3.7-) - suppress deprecation warning
|
||||
else:
|
||||
with warnings.catch_warnings():
|
||||
warnings.filterwarnings('ignore', category=DeprecationWarning)
|
||||
if hasattr(ast, 'Str') and isinstance(kw.value, ast.Str):
|
||||
return kw.value.s
|
||||
return None
|
||||
|
||||
|
||||
def is_schema_call(call_node):
|
||||
"""Check if ast.Call is io.Schema() or Schema()"""
|
||||
func = call_node.func
|
||||
if isinstance(func, ast.Name) and func.id == 'Schema':
|
||||
return True
|
||||
elif isinstance(func, ast.Attribute) and func.attr == 'Schema':
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def extract_node_id_from_schema(class_node):
|
||||
"""
|
||||
Extract node_id from define_schema() method
|
||||
"""
|
||||
for item in class_node.body:
|
||||
if isinstance(item, ast.FunctionDef) and item.name == 'define_schema':
|
||||
# Walk through function body
|
||||
for stmt in ast.walk(item):
|
||||
if isinstance(stmt, ast.Call):
|
||||
# Check if it's Schema() call
|
||||
if is_schema_call(stmt):
|
||||
node_id = extract_keyword_value(stmt, 'node_id')
|
||||
if node_id:
|
||||
return node_id
|
||||
return None
|
||||
|
||||
|
||||
def extract_v3_nodes(code_text):
|
||||
"""
|
||||
Extract V3 node IDs using AST parsing
|
||||
Returns: set of node_id strings
|
||||
"""
|
||||
global parse_cnt
|
||||
|
||||
try:
|
||||
if parse_cnt % 100 == 0:
|
||||
print(".", end="", flush=True)
|
||||
parse_cnt += 1
|
||||
|
||||
with warnings.catch_warnings():
|
||||
warnings.filterwarnings('ignore', category=SyntaxWarning)
|
||||
warnings.filterwarnings('ignore', category=DeprecationWarning)
|
||||
tree = ast.parse(code_text)
|
||||
except (SyntaxError, UnicodeDecodeError):
|
||||
return set()
|
||||
|
||||
nodes = set()
|
||||
|
||||
# Find io.ComfyNode subclasses
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.ClassDef):
|
||||
# Check if inherits from ComfyNode
|
||||
if has_comfy_node_base(node):
|
||||
node_id = extract_node_id_from_schema(node)
|
||||
if node_id:
|
||||
nodes.add(node_id)
|
||||
|
||||
return nodes
|
||||
|
||||
|
||||
# scan
|
||||
def scan_in_file(filename, is_builtin=False):
|
||||
global builtin_nodes
|
||||
@ -112,7 +234,11 @@ def scan_in_file(filename, is_builtin=False):
|
||||
nodes = set()
|
||||
class_dict = {}
|
||||
|
||||
# V1 nodes detection
|
||||
nodes |= extract_nodes(code)
|
||||
|
||||
# V3 nodes detection
|
||||
nodes |= extract_v3_nodes(code)
|
||||
code = re.sub(r'^#.*?$', '', code, flags=re.MULTILINE)
|
||||
|
||||
def extract_keys(pattern, code):
|
||||
@ -209,6 +335,53 @@ def get_nodes(target_dir):
|
||||
return py_files, directories
|
||||
|
||||
|
||||
def get_urls_from_list_file(list_file):
|
||||
"""
|
||||
Read URLs from list file for scan-only mode
|
||||
|
||||
Args:
|
||||
list_file (str): Path to URL list file (one URL per line)
|
||||
|
||||
Returns:
|
||||
list of tuples: [(url, "", None, None), ...]
|
||||
Format: (url, title, preemptions, nodename_pattern)
|
||||
- title: Empty string
|
||||
- preemptions: None
|
||||
- nodename_pattern: None
|
||||
|
||||
File format:
|
||||
https://github.com/owner/repo1
|
||||
https://github.com/owner/repo2
|
||||
# Comments starting with # are ignored
|
||||
|
||||
Raises:
|
||||
FileNotFoundError: If list_file does not exist
|
||||
"""
|
||||
if not os.path.exists(list_file):
|
||||
raise FileNotFoundError(f"URL list file not found: {list_file}")
|
||||
|
||||
urls = []
|
||||
with open(list_file, 'r', encoding='utf-8') as f:
|
||||
for line_num, line in enumerate(f, 1):
|
||||
line = line.strip()
|
||||
|
||||
# Skip empty lines and comments
|
||||
if not line or line.startswith('#'):
|
||||
continue
|
||||
|
||||
# Validate URL format (basic check)
|
||||
if not (line.startswith('http://') or line.startswith('https://')):
|
||||
print(f"WARNING: Line {line_num} is not a valid URL: {line}")
|
||||
continue
|
||||
|
||||
# Add URL with empty metadata
|
||||
# (url, title, preemptions, nodename_pattern)
|
||||
urls.append((line, "", None, None))
|
||||
|
||||
print(f"Loaded {len(urls)} URLs from {list_file}")
|
||||
return urls
|
||||
|
||||
|
||||
def get_git_urls_from_json(json_file):
|
||||
with open(json_file, encoding='utf-8') as file:
|
||||
data = json.load(file)
|
||||
@ -265,13 +438,43 @@ def clone_or_pull_git_repository(git_url):
|
||||
print(f"Failed to clone '{repo_name}': {e}")
|
||||
|
||||
|
||||
def update_custom_nodes():
|
||||
def update_custom_nodes(scan_only_mode=False, url_list_file=None):
|
||||
"""
|
||||
Update custom nodes by cloning/pulling repositories
|
||||
|
||||
Args:
|
||||
scan_only_mode (bool): If True, use URL list file instead of custom-node-list.json
|
||||
url_list_file (str): Path to URL list file (required if scan_only_mode=True)
|
||||
|
||||
Returns:
|
||||
dict: node_info mapping {repo_name: (url, title, preemptions, node_pattern)}
|
||||
"""
|
||||
if not os.path.exists(temp_dir):
|
||||
os.makedirs(temp_dir)
|
||||
|
||||
node_info = {}
|
||||
|
||||
git_url_titles_preemptions = get_git_urls_from_json('custom-node-list.json')
|
||||
# Select URL source based on mode
|
||||
if scan_only_mode:
|
||||
if not url_list_file:
|
||||
raise ValueError("url_list_file is required in scan-only mode")
|
||||
|
||||
git_url_titles_preemptions = get_urls_from_list_file(url_list_file)
|
||||
print("\n[Scan-Only Mode]")
|
||||
print(f" - URL source: {url_list_file}")
|
||||
print(" - GitHub stats: DISABLED")
|
||||
print(f" - Git clone/pull: {'ENABLED' if not skip_update else 'DISABLED'}")
|
||||
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("\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(" - Metadata: FULL")
|
||||
|
||||
def process_git_url_title(url, title, preemptions, node_pattern):
|
||||
name = os.path.basename(url)
|
||||
@ -383,46 +586,59 @@ def update_custom_nodes():
|
||||
if not skip_stat_update:
|
||||
process_git_stats(git_url_titles_preemptions)
|
||||
|
||||
# Git clone/pull for all repositories
|
||||
with concurrent.futures.ThreadPoolExecutor(11) as executor:
|
||||
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')
|
||||
# .py file download (skip in scan-only mode - only process git repos)
|
||||
if not scan_only_mode:
|
||||
py_url_titles_and_pattern = get_py_urls_from_json('custom-node-list.json')
|
||||
|
||||
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, preemptions, node_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, preemptions, node_pattern)
|
||||
|
||||
try:
|
||||
download_url(url, temp_dir)
|
||||
except:
|
||||
print(f"[ERROR] Cannot download '{url}'")
|
||||
try:
|
||||
download_url(url, temp_dir)
|
||||
except:
|
||||
print(f"[ERROR] Cannot download '{url}'")
|
||||
|
||||
with concurrent.futures.ThreadPoolExecutor(10) as executor:
|
||||
executor.map(download_and_store_info, py_url_titles_and_pattern)
|
||||
with concurrent.futures.ThreadPoolExecutor(10) as executor:
|
||||
executor.map(download_and_store_info, py_url_titles_and_pattern)
|
||||
|
||||
return node_info
|
||||
|
||||
|
||||
def gen_json(node_info):
|
||||
def gen_json(node_info, scan_only_mode=False):
|
||||
"""
|
||||
Generate extension-node-map.json from scanned node information
|
||||
|
||||
Args:
|
||||
node_info (dict): Repository metadata mapping
|
||||
scan_only_mode (bool): If True, exclude metadata from output
|
||||
"""
|
||||
# scan from .py file
|
||||
node_files, node_dirs = get_nodes(temp_dir)
|
||||
|
||||
comfyui_path = os.path.abspath(os.path.join(temp_dir, "ComfyUI"))
|
||||
node_dirs.remove(comfyui_path)
|
||||
node_dirs = [comfyui_path] + node_dirs
|
||||
# Only reorder if ComfyUI exists in the list
|
||||
if comfyui_path in node_dirs:
|
||||
node_dirs.remove(comfyui_path)
|
||||
node_dirs = [comfyui_path] + node_dirs
|
||||
|
||||
data = {}
|
||||
for dirname in node_dirs:
|
||||
py_files = get_py_file_paths(dirname)
|
||||
metadata = {}
|
||||
|
||||
|
||||
nodes = set()
|
||||
for py in py_files:
|
||||
nodes_in_file, metadata_in_file = scan_in_file(py, dirname == "ComfyUI")
|
||||
nodes.update(nodes_in_file)
|
||||
# Include metadata from .py files in both modes
|
||||
metadata.update(metadata_in_file)
|
||||
|
||||
dirname = os.path.basename(dirname)
|
||||
@ -437,17 +653,28 @@ def gen_json(node_info):
|
||||
if dirname in node_info:
|
||||
git_url, title, preemptions, node_pattern = node_info[dirname]
|
||||
|
||||
metadata['title_aux'] = title
|
||||
# Conditionally add metadata based on mode
|
||||
if not scan_only_mode:
|
||||
# Standard mode: include all metadata
|
||||
metadata['title_aux'] = title
|
||||
|
||||
if preemptions is not None:
|
||||
metadata['preemptions'] = preemptions
|
||||
if preemptions is not None:
|
||||
metadata['preemptions'] = preemptions
|
||||
|
||||
if node_pattern is not None:
|
||||
metadata['nodename_pattern'] = node_pattern
|
||||
if node_pattern is not None:
|
||||
metadata['nodename_pattern'] = node_pattern
|
||||
# Scan-only mode: metadata remains empty
|
||||
|
||||
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)
|
||||
@ -460,13 +687,16 @@ def gen_json(node_info):
|
||||
|
||||
if file in node_info:
|
||||
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
|
||||
# Conditionally add metadata based on mode
|
||||
if not scan_only_mode:
|
||||
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:
|
||||
@ -478,6 +708,10 @@ 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):
|
||||
# Skip if extension not in node_info (scan-only mode with limited URLs)
|
||||
if extension not in node_info:
|
||||
continue
|
||||
|
||||
git_url, title, preemptions, node_pattern = node_info[extension]
|
||||
|
||||
with open(node_list_json_path, 'r', encoding='utf-8') as f:
|
||||
@ -507,14 +741,16 @@ def gen_json(node_info):
|
||||
print("------------------------------------------------------")
|
||||
node_list_json = {}
|
||||
|
||||
metadata_in_url['title_aux'] = title
|
||||
# Conditionally add metadata based on mode
|
||||
if not scan_only_mode:
|
||||
metadata_in_url['title_aux'] = title
|
||||
|
||||
if preemptions is not None:
|
||||
metadata['preemptions'] = preemptions
|
||||
if preemptions is not None:
|
||||
metadata_in_url['preemptions'] = preemptions
|
||||
|
||||
if node_pattern is not None:
|
||||
metadata_in_url['nodename_pattern'] = node_pattern
|
||||
|
||||
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)
|
||||
@ -524,12 +760,53 @@ def gen_json(node_info):
|
||||
json.dump(data, file, indent=4, sort_keys=True)
|
||||
|
||||
|
||||
print("### ComfyUI Manager Node Scanner ###")
|
||||
if __name__ == "__main__":
|
||||
# Parse arguments
|
||||
args = parse_arguments()
|
||||
|
||||
print("\n# Updating extensions\n")
|
||||
updated_node_info = update_custom_nodes()
|
||||
# Determine mode
|
||||
scan_only_mode = args.scan_only is not None
|
||||
url_list_file = args.scan_only if scan_only_mode else None
|
||||
|
||||
print("\n# 'extension-node-map.json' file is generated.\n")
|
||||
gen_json(updated_node_info)
|
||||
# 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("\nDONE.\n")
|
||||
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("### 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