Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
816a53a7b1 | ||
|
|
ced93b0525 | ||
|
|
524ff9a4a6 | ||
|
|
f15032f905 | ||
|
|
d7d31a19e5 | ||
|
|
df2a7ddca4 | ||
|
|
ba9c71ffa4 | ||
|
|
21b6c6569c | ||
|
|
92aba9565a | ||
|
|
6ea0aebb0b | ||
|
|
b5cdcb75b4 | ||
|
|
bd9aae40b8 | ||
|
|
33f931c0a4 | ||
|
|
ede8279c17 | ||
|
|
268b84a2b6 | ||
|
|
0a67145d80 | ||
|
|
2e55bc470c | ||
|
|
cf0d038978 | ||
|
|
92e7db1082 | ||
|
|
c45c47f935 | ||
|
|
341e27f9a3 | ||
|
|
ab167175c9 | ||
|
|
3c2933338f | ||
|
|
829784fa50 | ||
|
|
3c45f8dc91 | ||
|
|
f8ebf7c6ad | ||
|
|
510c364607 | ||
|
|
a3d6fcccb7 |
20
README.md
20
README.md
@@ -5,6 +5,7 @@
|
|||||||

|

|
||||||
|
|
||||||
## NOTICE
|
## NOTICE
|
||||||
|
* V3.16: Support for `uv` has been added. Set `use_uv` in `config.ini`.
|
||||||
* V3.10: `double-click feature` is removed
|
* V3.10: `double-click feature` is removed
|
||||||
* This feature has been moved to https://github.com/ltdrdata/comfyui-connection-helper
|
* This feature has been moved to https://github.com/ltdrdata/comfyui-connection-helper
|
||||||
* V3.3.2: Overhauled. Officially supports [https://comfyregistry.org/](https://comfyregistry.org/).
|
* V3.3.2: Overhauled. Officially supports [https://comfyregistry.org/](https://comfyregistry.org/).
|
||||||
@@ -246,6 +247,25 @@ The following settings are applied based on the section marked as `is_default`.
|
|||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
# Config
|
||||||
|
* You can modify the `config.ini` file to apply the settings for ComfyUI-Manager.
|
||||||
|
* The path to the `config.ini` used by ComfyUI-Manager is displayed in the startup log messages.
|
||||||
|
* See also: [https://github.com/ltdrdata/ComfyUI-Manager#paths]
|
||||||
|
* Configuration options:
|
||||||
|
```
|
||||||
|
[default]
|
||||||
|
git_exe = <Manually specify the path to the git executable. If left empty, the default git executable path will be used.>
|
||||||
|
use_uv = <Use uv instead of pip for dependency installation.>
|
||||||
|
default_cache_as_channel_url = <Determines whether to retrieve the DB designated as channel_url at startup>
|
||||||
|
bypass_ssl = <Set to True if SSL errors occur to disable SSL.>
|
||||||
|
file_logging = <Configure whether to create a log file used by ComfyUI-Manager.>
|
||||||
|
windows_selector_event_loop_policy = <If an event loop error occurs on Windows, set this to True.>
|
||||||
|
model_download_by_agent = <When downloading models, use an agent instead of torchvision_download_url.>
|
||||||
|
downgrade_blacklist = <Set a list of packages to prevent downgrades. List them separated by commas.>
|
||||||
|
security_level = <Set the security level.>
|
||||||
|
always_lazy_install = <Whether to perform dependency installation on restart even in environments other than Windows.>
|
||||||
|
```
|
||||||
|
|
||||||
## Additional Feature
|
## Additional Feature
|
||||||
* Logging to file feature
|
* Logging to file feature
|
||||||
* This feature is enabled by default and can be disabled by setting `file_logging = False` in the `config.ini`.
|
* This feature is enabled by default and can be disabled by setting `file_logging = False` in the `config.ini`.
|
||||||
|
|||||||
@@ -4067,6 +4067,17 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Image metrics nodes for ComfyUI"
|
"description": "Image metrics nodes for ComfyUI"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"author": "amorano",
|
||||||
|
"title": "Jovi_MIDI",
|
||||||
|
"id": "jovi_midi",
|
||||||
|
"reference": "https://github.com/Amorano/Jovi_MIDI",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/Amorano/Jovi_MIDI"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Read and Process data from MIDI devices inside of ComfyUI."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "Umikaze-job",
|
"author": "Umikaze-job",
|
||||||
"title": "select_folder_path_easy",
|
"title": "select_folder_path_easy",
|
||||||
@@ -5097,7 +5108,7 @@
|
|||||||
"https://github.com/MNeMoNiCuZ/ComfyUI-mnemic-nodes"
|
"https://github.com/MNeMoNiCuZ/ComfyUI-mnemic-nodes"
|
||||||
],
|
],
|
||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Added new models to Groq LLM. Added a new node: Tiktoken Tokenizer Info."
|
"description": "Added Lora Loader - Tag node, originally by badjeff"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "AI2lab",
|
"author": "AI2lab",
|
||||||
@@ -6496,6 +6507,16 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Add nodes that generates danbooru tags by [a/Dart(Danbooru Tags Transformer)](https://huggingface.co/p1atdev/dart-v1-sft)."
|
"description": "Add nodes that generates danbooru tags by [a/Dart(Danbooru Tags Transformer)](https://huggingface.co/p1atdev/dart-v1-sft)."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"author": "nkchocoai",
|
||||||
|
"title": "ComfyUI-DanbooruPromptQuiz",
|
||||||
|
"reference": "https://github.com/nkchocoai/ComfyUI-DanbooruPromptQuiz",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/nkchocoai/ComfyUI-DanbooruPromptQuiz"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "This node is for playing the game of guessing prompts by looking at images generated from prompts output by TIPO, Tagger, etc.."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "JaredTherriault",
|
"author": "JaredTherriault",
|
||||||
"title": "ComfyUI-JNodes",
|
"title": "ComfyUI-JNodes",
|
||||||
@@ -11042,6 +11063,16 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Custom node for using Prompt S/R in XY Plot\nAlso includes nodes for listing generic parameters like seed and cfg\nEasy to manipulate as elements are separated by line breaks\nDesigned for use with the XY Plot custom node qq-nodes-comfyui, but may work with other custom nodes as well"
|
"description": "Custom node for using Prompt S/R in XY Plot\nAlso includes nodes for listing generic parameters like seed and cfg\nEasy to manipulate as elements are separated by line breaks\nDesigned for use with the XY Plot custom node qq-nodes-comfyui, but may work with other custom nodes as well"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"author": "da2el-ai",
|
||||||
|
"title": "D2-PromptSelector-comfyUI",
|
||||||
|
"reference": "https://github.com/da2el-ai/D2-PromptSelector-comfyUI",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/da2el-ai/D2-PromptSelector-comfyUI"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "This is a version of [a/sd-d2-prompt-selector](https://github.com/da2el-ai/sd-d2-prompt-selector) reworked for ComfyUI. It's just a prototype that I've put together for now. The random syntax of sd-d2-prompt-selector cannot be used; instead, the DynamicPrompt syntax is used"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "nat-chan",
|
"author": "nat-chan",
|
||||||
"title": "ComfyUI-Transceiver📡",
|
"title": "ComfyUI-Transceiver📡",
|
||||||
@@ -19966,7 +19997,7 @@
|
|||||||
"https://github.com/DJ-Tribefull/Comfyui_FOCUS_nodes"
|
"https://github.com/DJ-Tribefull/Comfyui_FOCUS_nodes"
|
||||||
],
|
],
|
||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "This is a small collection of nodes designed for efficiency and the reduction of screen clutter. I work primarily with a two-stage SDXL workflow, so some of the nodes are tailored to that, but many of the most useful nodes can be used in any context."
|
"description": "A collection of nodes designed for efficiency and the reduction of screen-clutter. Includes a Global Seed controller with boolean toggles, SDXL All-in-One conditioner, a custom SDXL control module, Wildcard processor, Style Injector, and more. [w/WARNING: Updating this node-pack wil overwrite any changes you've made to the included wildcards and styles. Please backup your folders before updating.]"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "KLL535",
|
"author": "KLL535",
|
||||||
@@ -20190,7 +20221,18 @@
|
|||||||
"https://github.com/ProGamerGov/ComfyUI_pytorch360convert"
|
"https://github.com/ProGamerGov/ComfyUI_pytorch360convert"
|
||||||
],
|
],
|
||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "A collection of custom nodes for working with and converting between 360 degree equirectangular images, cubemap, and perspective images. Panoramic 360 images are also sometimes known as VR photography (virtual reality), HDRI environments (ex: skyboxes), image spheres, spherical images, 360 pano."
|
"description": "A collection of custom nodes for working with and converting between 360 degree equirectangular images, cubemap, and perspective images. Panoramic 360 images are also sometimes known as VR photography (virtual reality), HDRI environments (ex: skyboxes), image spheres, spherical images, 360 pano, and 360 degree photos."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "ProGamerGov",
|
||||||
|
"title": "Preview 360 Panorama for ComfyUI",
|
||||||
|
"id": "comfyui-preview360panorama",
|
||||||
|
"reference": "https://github.com/ProGamerGov/ComfyUI_preview360panorama",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/ProGamerGov/ComfyUI_preview360panorama"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A custom ComfyUI node for interactive 360° panorama image previews. Panoramic 360 images are also sometimes known as VR photography (virtual reality), HDRI environments (ex: skyboxes), image spheres, spherical images, 360 pano, and 360 degree photos."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "burnsbert",
|
"author": "burnsbert",
|
||||||
@@ -20251,7 +20293,7 @@
|
|||||||
"https://github.com/willmiao/ComfyUI-Lora-Manager"
|
"https://github.com/willmiao/ComfyUI-Lora-Manager"
|
||||||
],
|
],
|
||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "LoRA Manager for ComfyUI - An extension for managing LoRA models with previews and metadata integration."
|
"description": "LoRA Manager for ComfyUI - Access it at http://localhost:8188/loras for managing LoRA models with previews and metadata integration."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "tigeryy2",
|
"author": "tigeryy2",
|
||||||
@@ -20364,6 +20406,28 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "This node group contains a series of ComfyUI nodes with built-in counters and specific output results based on the counter's output, aimed at implementing folder traversal functionality in the ComfyUI frontend. For specific examples, please refer to the sample workflow. Of course, you can also use your imagination to create other interesting things."
|
"description": "This node group contains a series of ComfyUI nodes with built-in counters and specific output results based on the counter's output, aimed at implementing folder traversal functionality in the ComfyUI frontend. For specific examples, please refer to the sample workflow. Of course, you can also use your imagination to create other interesting things."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"author": "agilly1989",
|
||||||
|
"title": "ComfyUI_agilly1989_motorway",
|
||||||
|
"reference": "https://github.com/agilly1989/ComfyUI_agilly1989_motorway",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/agilly1989/ComfyUI_agilly1989_motorway"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "This my implemenation of a `pipe` in ComfyUI. Is it better or worse than others? No idea."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "AiartvnTeam",
|
||||||
|
"title": "A2V Multi Image Composite",
|
||||||
|
"id": "Aiartvn",
|
||||||
|
"reference": "https://github.com/aiartvn/A2V_Multi_Image_Composite",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/aiartvn/A2V_Multi_Image_Composite"
|
||||||
|
],
|
||||||
|
"description": "Node for compositing multiple images with interactive preview and layer management",
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"tags": ["image", "composite", "layer", "blend", "transform"]
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -493,6 +493,7 @@
|
|||||||
"https://github.com/852wa/ComfyUI-ColorshiftColor": [
|
"https://github.com/852wa/ComfyUI-ColorshiftColor": [
|
||||||
[
|
[
|
||||||
"ColorshiftColor",
|
"ColorshiftColor",
|
||||||
|
"CsCFill",
|
||||||
"CsCPaletteEditor"
|
"CsCPaletteEditor"
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
@@ -1427,6 +1428,18 @@
|
|||||||
"title_aux": "Jovi_GLSL"
|
"title_aux": "Jovi_GLSL"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/Amorano/Jovi_MIDI": [
|
||||||
|
[
|
||||||
|
"MIDI FILTER (JOV_MIDI)",
|
||||||
|
"MIDI FILTER EZ (JOV_MIDI)",
|
||||||
|
"MIDI LOADER (JOV_MIDI)",
|
||||||
|
"MIDI MESSAGE (JOV_MIDI)",
|
||||||
|
"MIDI READER (JOV_MIDI)"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "Jovi_MIDI"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/Amorano/Jovi_Measure": [
|
"https://github.com/Amorano/Jovi_Measure": [
|
||||||
[
|
[
|
||||||
"BLUR EFFECT (JOV_MEASURE)",
|
"BLUR EFFECT (JOV_MEASURE)",
|
||||||
@@ -2818,11 +2831,17 @@
|
|||||||
],
|
],
|
||||||
"https://github.com/DesertPixelAi/ComfyUI-Desert-Pixel-Nodes": [
|
"https://github.com/DesertPixelAi/ComfyUI-Desert-Pixel-Nodes": [
|
||||||
[
|
[
|
||||||
"DP 10 String Switch",
|
"DP 10 Images Switch Or Batch",
|
||||||
|
"DP 10 String Switch Or Connect",
|
||||||
"DP 2 String Switch",
|
"DP 2 String Switch",
|
||||||
|
"DP 3 Images Switch Or Batch",
|
||||||
|
"DP 3 String Switch Or Connect",
|
||||||
"DP 5 Find And Replace",
|
"DP 5 Find And Replace",
|
||||||
"DP 5 String Switch",
|
"DP 5 Images Switch Or Batch",
|
||||||
|
"DP 5 String Switch Or Connect",
|
||||||
|
"DP Add Background To Png",
|
||||||
"DP Add Weight To String Sdxl",
|
"DP Add Weight To String Sdxl",
|
||||||
|
"DP Advanced Sampler",
|
||||||
"DP Advanced Weight String Sdxl",
|
"DP Advanced Weight String Sdxl",
|
||||||
"DP Animation Calculator 10 Inputs",
|
"DP Animation Calculator 10 Inputs",
|
||||||
"DP Animation Calculator 5 Inputs",
|
"DP Animation Calculator 5 Inputs",
|
||||||
@@ -2832,8 +2851,7 @@
|
|||||||
"DP Broken Token",
|
"DP Broken Token",
|
||||||
"DP Clean Prompt",
|
"DP Clean Prompt",
|
||||||
"DP Clean Prompt Travel",
|
"DP Clean Prompt Travel",
|
||||||
"DP Combo Controller",
|
"DP Condition Switch",
|
||||||
"DP Condition Mixer",
|
|
||||||
"DP ControlNet Apply Advanced",
|
"DP ControlNet Apply Advanced",
|
||||||
"DP Crazy Prompt Mixer",
|
"DP Crazy Prompt Mixer",
|
||||||
"DP Create Json File",
|
"DP Create Json File",
|
||||||
@@ -2845,6 +2863,7 @@
|
|||||||
"DP Fast Slow Motion",
|
"DP Fast Slow Motion",
|
||||||
"DP Five Lora",
|
"DP Five Lora",
|
||||||
"DP Five Lora Random",
|
"DP Five Lora Random",
|
||||||
|
"DP Float Stepper",
|
||||||
"DP Image And String Pairs Switch",
|
"DP Image And String Pairs Switch",
|
||||||
"DP Image Color Analyzer",
|
"DP Image Color Analyzer",
|
||||||
"DP Image Color Analyzer Small",
|
"DP Image Color Analyzer Small",
|
||||||
@@ -2855,12 +2874,10 @@
|
|||||||
"DP Image Empty Latent Switch SDXL",
|
"DP Image Empty Latent Switch SDXL",
|
||||||
"DP Image Slide Show",
|
"DP Image Slide Show",
|
||||||
"DP Image Strip",
|
"DP Image Strip",
|
||||||
"DP Image Switch 10",
|
|
||||||
"DP Image Switch 3",
|
|
||||||
"DP Image Switch 5",
|
|
||||||
"DP Int 0-1000",
|
"DP Int 0-1000",
|
||||||
"DP Int 0-1000 4 Step",
|
"DP Int 0-1000 4 Step",
|
||||||
"DP Int 0-1000 8 Step",
|
"DP Int 0-1000 8 Step",
|
||||||
|
"DP Latent Split",
|
||||||
"DP Line Cycler",
|
"DP Line Cycler",
|
||||||
"DP Load Checkpoint With Info",
|
"DP Load Checkpoint With Info",
|
||||||
"DP Load Controlnet Model With Name",
|
"DP Load Controlnet Model With Name",
|
||||||
@@ -2870,13 +2887,10 @@
|
|||||||
"DP Load Image Minimal",
|
"DP Load Image Minimal",
|
||||||
"DP Load UNET With Info",
|
"DP Load UNET With Info",
|
||||||
"DP Logo Animator",
|
"DP Logo Animator",
|
||||||
"DP Logo Animator Advanced",
|
|
||||||
"DP Lora Random Strength Controller",
|
"DP Lora Random Strength Controller",
|
||||||
"DP Lora Strength Controller",
|
"DP Lora Strength Controller",
|
||||||
"DP Lora Strength Stepper",
|
|
||||||
"DP Mask Settings",
|
"DP Mask Settings",
|
||||||
"DP Prompt Inverter",
|
"DP Prompt Inverter",
|
||||||
"DP Prompt Manager",
|
|
||||||
"DP Prompt Manager Small",
|
"DP Prompt Manager Small",
|
||||||
"DP Prompt Mode Controller",
|
"DP Prompt Mode Controller",
|
||||||
"DP Prompt Styler",
|
"DP Prompt Styler",
|
||||||
@@ -2894,9 +2908,7 @@
|
|||||||
"DP Save Preview Image",
|
"DP Save Preview Image",
|
||||||
"DP Set New Model Folder Link",
|
"DP Set New Model Folder Link",
|
||||||
"DP String Text",
|
"DP String Text",
|
||||||
"DP String Text With Weight",
|
"DP String Text With Sdxl Weight",
|
||||||
"DP String With Switch",
|
|
||||||
"DP Strings Connector",
|
|
||||||
"DP Strip Edge Masks",
|
"DP Strip Edge Masks",
|
||||||
"DP Switch Controller",
|
"DP Switch Controller",
|
||||||
"DP Text Preview",
|
"DP Text Preview",
|
||||||
@@ -2907,10 +2919,8 @@
|
|||||||
"DP Video Looper",
|
"DP Video Looper",
|
||||||
"DP Video Transition",
|
"DP Video Transition",
|
||||||
"DP_Crazy_Prompt_Mixer",
|
"DP_Crazy_Prompt_Mixer",
|
||||||
"DP_Logo_Animator_Advanced",
|
"DP_Float_Stepper",
|
||||||
"DP_Lora_Strength_Stepper",
|
"DP_Prompt_Inverter"
|
||||||
"DP_Prompt_Inverter",
|
|
||||||
"DP_Strings_Connector"
|
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
"title_aux": "ComfyUI-Desert-Pixel-Nodes"
|
"title_aux": "ComfyUI-Desert-Pixel-Nodes"
|
||||||
@@ -4714,6 +4724,8 @@
|
|||||||
],
|
],
|
||||||
"https://github.com/JTriggerFish/ComfyLatentTools": [
|
"https://github.com/JTriggerFish/ComfyLatentTools": [
|
||||||
[
|
[
|
||||||
|
"DownsampledAttentionGuidance",
|
||||||
|
"DownsampledLatentGuidance",
|
||||||
"LatentNormalizedLanczosResize",
|
"LatentNormalizedLanczosResize",
|
||||||
"RescaledPAG",
|
"RescaledPAG",
|
||||||
"RescaledSEG"
|
"RescaledSEG"
|
||||||
@@ -5018,6 +5030,7 @@
|
|||||||
[
|
[
|
||||||
"Simple Extract Lora From Text",
|
"Simple Extract Lora From Text",
|
||||||
"Simple Image Saver (as Forge)",
|
"Simple Image Saver (as Forge)",
|
||||||
|
"Simple Load Image With Metadata",
|
||||||
"Simple Load Line From Text File",
|
"Simple Load Line From Text File",
|
||||||
"Simple Lora Loader"
|
"Simple Lora Loader"
|
||||||
],
|
],
|
||||||
@@ -5841,6 +5854,7 @@
|
|||||||
],
|
],
|
||||||
"https://github.com/MNeMoNiCuZ/ComfyUI-mnemic-nodes": [
|
"https://github.com/MNeMoNiCuZ/ComfyUI-mnemic-nodes": [
|
||||||
[
|
[
|
||||||
|
"LoraTagLoader",
|
||||||
"StringCleaning",
|
"StringCleaning",
|
||||||
"TiktokenTokenizer",
|
"TiktokenTokenizer",
|
||||||
"\u26d4 Generate Negative Prompt",
|
"\u26d4 Generate Negative Prompt",
|
||||||
@@ -5848,6 +5862,7 @@
|
|||||||
"\u2728\ud83d\udcac Groq LLM API",
|
"\u2728\ud83d\udcac Groq LLM API",
|
||||||
"\u2728\ud83d\udcdd Groq ALM API - Transcribe",
|
"\u2728\ud83d\udcdd Groq ALM API - Transcribe",
|
||||||
"\u2728\ud83d\udcf7 Groq VLM API",
|
"\u2728\ud83d\udcf7 Groq VLM API",
|
||||||
|
"\ud83c\udff7\ufe0f LoRA Loader Prompt Tags",
|
||||||
"\ud83d\udcbe Save Text File With Path",
|
"\ud83d\udcbe Save Text File With Path",
|
||||||
"\ud83d\udcc1 Get File Path",
|
"\ud83d\udcc1 Get File Path",
|
||||||
"\ud83d\udd20 Tiktoken Tokenizer Info",
|
"\ud83d\udd20 Tiktoken Tokenizer Info",
|
||||||
@@ -6434,10 +6449,13 @@
|
|||||||
],
|
],
|
||||||
"https://github.com/MzMaXaM/ComfyUi-MzMaXaM": [
|
"https://github.com/MzMaXaM/ComfyUi-MzMaXaM": [
|
||||||
[
|
[
|
||||||
|
"ImageToText",
|
||||||
"KSamplerWithVAE",
|
"KSamplerWithVAE",
|
||||||
"SelectLatentSize1MP",
|
"SelectLatentSize1MP",
|
||||||
"SelectLatentSize2MP",
|
"SelectLatentSize2MP",
|
||||||
"TextEncode3in1",
|
"TextEncode3in1",
|
||||||
|
"TextToText",
|
||||||
|
"UpscaleImageBy1_5x",
|
||||||
"UpscaleLatentBy1_5x"
|
"UpscaleLatentBy1_5x"
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
@@ -7061,6 +7079,14 @@
|
|||||||
"title_aux": "ComfyUI-StringsAndThings"
|
"title_aux": "ComfyUI-StringsAndThings"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/ProGamerGov/ComfyUI_preview360panorama": [
|
||||||
|
[
|
||||||
|
"PanoramaViewerNode"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "Preview 360 Panorama for ComfyUI"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/ProGamerGov/ComfyUI_pytorch360convert": [
|
"https://github.com/ProGamerGov/ComfyUI_pytorch360convert": [
|
||||||
[
|
[
|
||||||
"Crop Image with Coords",
|
"Crop Image with Coords",
|
||||||
@@ -7351,6 +7377,7 @@
|
|||||||
"AspectRatioAdvanced",
|
"AspectRatioAdvanced",
|
||||||
"DisplayEverything",
|
"DisplayEverything",
|
||||||
"ImageComparer",
|
"ImageComparer",
|
||||||
|
"LensFlare",
|
||||||
"MultiFloat",
|
"MultiFloat",
|
||||||
"MultiTextNode",
|
"MultiTextNode",
|
||||||
"SKB_AnySwitch",
|
"SKB_AnySwitch",
|
||||||
@@ -8450,8 +8477,10 @@
|
|||||||
"SD35StartSettings",
|
"SD35StartSettings",
|
||||||
"SDXLStartSettings",
|
"SDXLStartSettings",
|
||||||
"SDstarsampler",
|
"SDstarsampler",
|
||||||
|
"Star Face Loader",
|
||||||
"StarFiveWildcards",
|
"StarFiveWildcards",
|
||||||
"StarImageSwitch",
|
"StarImageSwitch",
|
||||||
|
"StarLatentSwitch",
|
||||||
"StarTextFilter",
|
"StarTextFilter",
|
||||||
"StarTextInput",
|
"StarTextInput",
|
||||||
"Starupscale"
|
"Starupscale"
|
||||||
@@ -10646,6 +10675,18 @@
|
|||||||
"title_aux": "ComfyUI-styles-all"
|
"title_aux": "ComfyUI-styles-all"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/agilly1989/ComfyUI_agilly1989_motorway": [
|
||||||
|
[
|
||||||
|
"MotorwayFloat",
|
||||||
|
"MotorwayInt",
|
||||||
|
"MotorwaySeed",
|
||||||
|
"MotorwayStr",
|
||||||
|
"MotorwayStrMulti"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "ComfyUI_agilly1989_motorway"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/ahernandezmiro/ComfyUI-GCP_Storage_tools": [
|
"https://github.com/ahernandezmiro/ComfyUI-GCP_Storage_tools": [
|
||||||
[
|
[
|
||||||
"GCPReadImageNode",
|
"GCPReadImageNode",
|
||||||
@@ -10721,6 +10762,14 @@
|
|||||||
"title_aux": "Comfy UI FatLabels"
|
"title_aux": "Comfy UI FatLabels"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/aiartvn/A2V_Multi_Image_Composite": [
|
||||||
|
[
|
||||||
|
"A2V_Multi_Image_Composite"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "A2V Multi Image Composite"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/aidec/Comfyui_TextBatch_aidec": [
|
"https://github.com/aidec/Comfyui_TextBatch_aidec": [
|
||||||
[
|
[
|
||||||
"ImageQueueProcessor",
|
"ImageQueueProcessor",
|
||||||
@@ -11881,18 +11930,22 @@
|
|||||||
"SamplerSonarEuler",
|
"SamplerSonarEuler",
|
||||||
"SamplerSonarEulerA",
|
"SamplerSonarEulerA",
|
||||||
"SonarAdvanced1fNoise",
|
"SonarAdvanced1fNoise",
|
||||||
|
"SonarAdvancedDistroNoise",
|
||||||
"SonarAdvancedPowerLawNoise",
|
"SonarAdvancedPowerLawNoise",
|
||||||
"SonarAdvancedPyramidNoise",
|
"SonarAdvancedPyramidNoise",
|
||||||
"SonarBlendedNoise",
|
"SonarBlendedNoise",
|
||||||
"SonarChannelNoise",
|
"SonarChannelNoise",
|
||||||
"SonarCompositeNoise",
|
"SonarCompositeNoise",
|
||||||
"SonarCustomNoise",
|
"SonarCustomNoise",
|
||||||
|
"SonarCustomNoiseAdv",
|
||||||
"SonarGuidanceConfig",
|
"SonarGuidanceConfig",
|
||||||
"SonarGuidedNoise",
|
"SonarGuidedNoise",
|
||||||
"SonarModulatedNoise",
|
"SonarModulatedNoise",
|
||||||
"SonarRandomNoise",
|
"SonarRandomNoise",
|
||||||
"SonarRepeatedNoise",
|
"SonarRepeatedNoise",
|
||||||
"SonarScheduledNoise"
|
"SonarResizedNoise",
|
||||||
|
"SonarScheduledNoise",
|
||||||
|
"SonarWaveletFilteredNoise"
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
"title_aux": "ComfyUI-sonar"
|
"title_aux": "ComfyUI-sonar"
|
||||||
@@ -13897,6 +13950,7 @@
|
|||||||
"PolyexponentialScheduler",
|
"PolyexponentialScheduler",
|
||||||
"PorterDuffImageComposite",
|
"PorterDuffImageComposite",
|
||||||
"Preview3D",
|
"Preview3D",
|
||||||
|
"Preview3DAnimation",
|
||||||
"PreviewAudio",
|
"PreviewAudio",
|
||||||
"PreviewImage",
|
"PreviewImage",
|
||||||
"RandomNoise",
|
"RandomNoise",
|
||||||
@@ -15452,7 +15506,8 @@
|
|||||||
"SelOutModel",
|
"SelOutModel",
|
||||||
"SelOutPolar",
|
"SelOutPolar",
|
||||||
"Selector",
|
"Selector",
|
||||||
"Selector Advanced"
|
"Selector Advanced",
|
||||||
|
"Selector Hub"
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
"author": "\"\u02f6\ud835\udfa2\u292c\u2ad2\u2d56s\u143c\u02f6\"",
|
"author": "\"\u02f6\ud835\udfa2\u292c\u2ad2\u2d56s\u143c\u02f6\"",
|
||||||
@@ -16638,8 +16693,10 @@
|
|||||||
"Griptape Replace: Rulesets on Agent",
|
"Griptape Replace: Rulesets on Agent",
|
||||||
"Griptape Replace: Tools on Agent",
|
"Griptape Replace: Tools on Agent",
|
||||||
"Griptape Rerank Driver: Cohere",
|
"Griptape Rerank Driver: Cohere",
|
||||||
|
"Griptape Retrieve: Cloud Ruleset",
|
||||||
"Griptape Run: Agent",
|
"Griptape Run: Agent",
|
||||||
"Griptape Run: Audio Transcription",
|
"Griptape Run: Audio Transcription",
|
||||||
|
"Griptape Run: Cloud Assistant",
|
||||||
"Griptape Run: Image Description",
|
"Griptape Run: Image Description",
|
||||||
"Griptape Run: Parallel Image Description",
|
"Griptape Run: Parallel Image Description",
|
||||||
"Griptape Run: Prompt Task",
|
"Griptape Run: Prompt Task",
|
||||||
@@ -19306,6 +19363,7 @@
|
|||||||
"GetImageRangeFromBatch",
|
"GetImageRangeFromBatch",
|
||||||
"GetImageSizeAndCount",
|
"GetImageSizeAndCount",
|
||||||
"GetImagesFromBatchIndexed",
|
"GetImagesFromBatchIndexed",
|
||||||
|
"GetLatentRangeFromBatch",
|
||||||
"GetLatentsFromBatchIndexed",
|
"GetLatentsFromBatchIndexed",
|
||||||
"GetMaskSizeAndCount",
|
"GetMaskSizeAndCount",
|
||||||
"GradientToFloat",
|
"GradientToFloat",
|
||||||
@@ -19324,6 +19382,7 @@
|
|||||||
"ImageGridComposite2x2",
|
"ImageGridComposite2x2",
|
||||||
"ImageGridComposite3x3",
|
"ImageGridComposite3x3",
|
||||||
"ImageGridtoBatch",
|
"ImageGridtoBatch",
|
||||||
|
"ImageNoiseAugmentation",
|
||||||
"ImageNormalize_Neg1_To_1",
|
"ImageNormalize_Neg1_To_1",
|
||||||
"ImagePadForOutpaintMasked",
|
"ImagePadForOutpaintMasked",
|
||||||
"ImagePadForOutpaintTargetSize",
|
"ImagePadForOutpaintTargetSize",
|
||||||
@@ -19339,6 +19398,7 @@
|
|||||||
"Intrinsic_lora_sampling",
|
"Intrinsic_lora_sampling",
|
||||||
"JoinStringMulti",
|
"JoinStringMulti",
|
||||||
"JoinStrings",
|
"JoinStrings",
|
||||||
|
"LeapfusionHunyuanI2VPatcher",
|
||||||
"LoadAndResizeImage",
|
"LoadAndResizeImage",
|
||||||
"LoadImagesFromFolderKJ",
|
"LoadImagesFromFolderKJ",
|
||||||
"LoadResAdapterNormalization",
|
"LoadResAdapterNormalization",
|
||||||
@@ -20733,6 +20793,7 @@
|
|||||||
"Enhanced Random Light Source",
|
"Enhanced Random Light Source",
|
||||||
"Float Relay",
|
"Float Relay",
|
||||||
"HLFrequencyDetailRestore",
|
"HLFrequencyDetailRestore",
|
||||||
|
"Hex to Color",
|
||||||
"Image Add Alpha",
|
"Image Add Alpha",
|
||||||
"Image Frequency Analyzer",
|
"Image Frequency Analyzer",
|
||||||
"Image Relay",
|
"Image Relay",
|
||||||
@@ -22574,6 +22635,15 @@
|
|||||||
"title_aux": "ComfyUI OpenAI Prompter"
|
"title_aux": "ComfyUI OpenAI Prompter"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/nkchocoai/ComfyUI-DanbooruPromptQuiz": [
|
||||||
|
[
|
||||||
|
"DanbooruPromptComparison",
|
||||||
|
"DanbooruPromptQuiz"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "ComfyUI-DanbooruPromptQuiz"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/nkchocoai/ComfyUI-Dart": [
|
"https://github.com/nkchocoai/ComfyUI-Dart": [
|
||||||
[
|
[
|
||||||
"DanbooruTagsTransformerBanTagsFromRegex",
|
"DanbooruTagsTransformerBanTagsFromRegex",
|
||||||
@@ -22679,11 +22749,11 @@
|
|||||||
],
|
],
|
||||||
"https://github.com/nofunstudio/Node_Fun_ComfyUI": [
|
"https://github.com/nofunstudio/Node_Fun_ComfyUI": [
|
||||||
[
|
[
|
||||||
|
"IframeView",
|
||||||
"LayeredInfiniteZoom",
|
"LayeredInfiniteZoom",
|
||||||
"Replicate flux 1.1 pro ultra",
|
"Replicate flux 1.1 pro ultra",
|
||||||
"ReplicateAPI_flux_1_1_pro_ultra",
|
"ReplicateAPI_flux_1_1_pro_ultra",
|
||||||
"ReplicateAPI_flux_fill_pro",
|
"ReplicateAPI_flux_fill_pro"
|
||||||
"WebViewer"
|
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
"title_aux": "Node_Fun_ComfyUI"
|
"title_aux": "Node_Fun_ComfyUI"
|
||||||
@@ -26163,6 +26233,7 @@
|
|||||||
"quadmoonChangeBackground",
|
"quadmoonChangeBackground",
|
||||||
"quadmoonConvertBoolToString",
|
"quadmoonConvertBoolToString",
|
||||||
"quadmoonConvertFloatToString",
|
"quadmoonConvertFloatToString",
|
||||||
|
"quadmoonConvertImageToPrompt",
|
||||||
"quadmoonConvertIntToString",
|
"quadmoonConvertIntToString",
|
||||||
"quadmoonConvertNormalizeHW",
|
"quadmoonConvertNormalizeHW",
|
||||||
"quadmoonConvertNumberToString",
|
"quadmoonConvertNumberToString",
|
||||||
@@ -27139,6 +27210,7 @@
|
|||||||
],
|
],
|
||||||
"https://github.com/xlinx/ComfyUI-decadetw-auto-prompt-llm": [
|
"https://github.com/xlinx/ComfyUI-decadetw-auto-prompt-llm": [
|
||||||
[
|
[
|
||||||
|
"Auto-LLM-Chat",
|
||||||
"Auto-LLM-Text",
|
"Auto-LLM-Text",
|
||||||
"Auto-LLM-Text-Vision",
|
"Auto-LLM-Text-Vision",
|
||||||
"Auto-LLM-Vision"
|
"Auto-LLM-Vision"
|
||||||
|
|||||||
4518
github-stats.json
4518
github-stats.json
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@ description:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
@@ -41,7 +42,7 @@ import manager_downloader
|
|||||||
from node_package import InstalledNodePackage
|
from node_package import InstalledNodePackage
|
||||||
|
|
||||||
|
|
||||||
version_code = [3, 12, 2]
|
version_code = [3, 17, 7]
|
||||||
version_str = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
|
version_str = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
|
||||||
|
|
||||||
|
|
||||||
@@ -173,7 +174,7 @@ git_script_path = os.path.join(manager_util.comfyui_manager_path, "git_helper.py
|
|||||||
manager_files_path = None
|
manager_files_path = None
|
||||||
manager_config_path = None
|
manager_config_path = None
|
||||||
manager_channel_list_path = None
|
manager_channel_list_path = None
|
||||||
manager_startup_script_path = None
|
manager_startup_script_path:str = None
|
||||||
manager_snapshot_path = None
|
manager_snapshot_path = None
|
||||||
manager_pip_overrides_path = None
|
manager_pip_overrides_path = None
|
||||||
manager_components_path = None
|
manager_components_path = None
|
||||||
@@ -324,6 +325,8 @@ def normalize_channel(channel):
|
|||||||
return None
|
return None
|
||||||
elif channel.startswith('https://'):
|
elif channel.startswith('https://'):
|
||||||
return channel
|
return channel
|
||||||
|
elif channel.startswith('http://') and get_config()['http_channel_enabled'] == True:
|
||||||
|
return channel
|
||||||
|
|
||||||
tmp_dict = get_channel_dict()
|
tmp_dict = get_channel_dict()
|
||||||
channel_url = tmp_dict.get(channel)
|
channel_url = tmp_dict.get(channel)
|
||||||
@@ -808,7 +811,7 @@ class UnifiedManager:
|
|||||||
package_name = remap_pip_package(line.strip())
|
package_name = remap_pip_package(line.strip())
|
||||||
if package_name and not package_name.startswith('#') and package_name not in self.processed_install:
|
if package_name and not package_name.startswith('#') and package_name not in self.processed_install:
|
||||||
self.processed_install.add(package_name)
|
self.processed_install.add(package_name)
|
||||||
install_cmd = [sys.executable, "-m", "pip", "install", package_name]
|
install_cmd = manager_util.make_pip_cmd(["install", package_name])
|
||||||
if package_name.strip() != "" and not package_name.startswith('#'):
|
if package_name.strip() != "" and not package_name.startswith('#'):
|
||||||
res = res and try_install_script(url, repo_path, install_cmd, instant_execution=instant_execution)
|
res = res and try_install_script(url, repo_path, install_cmd, instant_execution=instant_execution)
|
||||||
|
|
||||||
@@ -818,7 +821,7 @@ class UnifiedManager:
|
|||||||
if os.path.exists(install_script_path) and install_script_path not in self.processed_install:
|
if os.path.exists(install_script_path) and install_script_path not in self.processed_install:
|
||||||
self.processed_install.add(install_script_path)
|
self.processed_install.add(install_script_path)
|
||||||
print("Install: install script")
|
print("Install: install script")
|
||||||
install_cmd = [sys.executable, "install.py"]
|
install_cmd = manager_util.make_pip_cmd(["install.py"])
|
||||||
return try_install_script(url, repo_path, install_cmd, instant_execution=instant_execution)
|
return try_install_script(url, repo_path, install_cmd, instant_execution=instant_execution)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
@@ -1544,18 +1547,19 @@ def write_config():
|
|||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
config['default'] = {
|
config['default'] = {
|
||||||
'preview_method': manager_funcs.get_current_preview_method(),
|
'preview_method': manager_funcs.get_current_preview_method(),
|
||||||
'git_exe': get_config()['git_exe'],
|
'git_exe': get_config()['git_exe'],
|
||||||
|
'use_uv': get_config()['use_uv'],
|
||||||
'channel_url': get_config()['channel_url'],
|
'channel_url': get_config()['channel_url'],
|
||||||
'share_option': get_config()['share_option'],
|
'share_option': get_config()['share_option'],
|
||||||
'bypass_ssl': get_config()['bypass_ssl'],
|
'bypass_ssl': get_config()['bypass_ssl'],
|
||||||
"file_logging": get_config()['file_logging'],
|
"file_logging": get_config()['file_logging'],
|
||||||
'default_ui': get_config()['default_ui'],
|
|
||||||
'component_policy': get_config()['component_policy'],
|
'component_policy': get_config()['component_policy'],
|
||||||
'windows_selector_event_loop_policy': get_config()['windows_selector_event_loop_policy'],
|
'windows_selector_event_loop_policy': get_config()['windows_selector_event_loop_policy'],
|
||||||
'model_download_by_agent': get_config()['model_download_by_agent'],
|
'model_download_by_agent': get_config()['model_download_by_agent'],
|
||||||
'downgrade_blacklist': get_config()['downgrade_blacklist'],
|
'downgrade_blacklist': get_config()['downgrade_blacklist'],
|
||||||
'security_level': get_config()['security_level'],
|
'security_level': get_config()['security_level'],
|
||||||
'skip_migration_check': get_config()['skip_migration_check'],
|
'skip_migration_check': get_config()['skip_migration_check'],
|
||||||
|
'always_lazy_install': get_config()['always_lazy_install']
|
||||||
}
|
}
|
||||||
|
|
||||||
directory = os.path.dirname(manager_config_path)
|
directory = os.path.dirname(manager_config_path)
|
||||||
@@ -1581,36 +1585,45 @@ def read_config():
|
|||||||
else:
|
else:
|
||||||
security_level = default_conf['security_level'] if 'security_level' in default_conf else 'normal'
|
security_level = default_conf['security_level'] if 'security_level' in default_conf else 'normal'
|
||||||
|
|
||||||
|
manager_util.use_uv = default_conf['use_uv'].lower() == 'true' if 'use_uv' in default_conf else False
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
'http_channel_enabled': default_conf['http_channel_enabled'].lower() == 'true' if 'http_channel_enabled' in default_conf else False,
|
||||||
'preview_method': default_conf['preview_method'] if 'preview_method' in default_conf else manager_funcs.get_current_preview_method(),
|
'preview_method': default_conf['preview_method'] if 'preview_method' in default_conf else manager_funcs.get_current_preview_method(),
|
||||||
'git_exe': default_conf['git_exe'] if 'git_exe' in default_conf else '',
|
'git_exe': default_conf['git_exe'] if 'git_exe' in default_conf else '',
|
||||||
|
'use_uv': default_conf['use_uv'].lower() == 'true' if 'use_uv' in default_conf else False,
|
||||||
'channel_url': default_conf['channel_url'] if 'channel_url' in default_conf else DEFAULT_CHANNEL,
|
'channel_url': default_conf['channel_url'] if 'channel_url' in default_conf else DEFAULT_CHANNEL,
|
||||||
|
'default_cache_as_channel_url': default_conf['default_cache_as_channel_url'].lower() == 'true' if 'default_cache_as_channel_url' in default_conf else False,
|
||||||
'share_option': default_conf['share_option'] if 'share_option' in default_conf else 'all',
|
'share_option': default_conf['share_option'] if 'share_option' in default_conf else 'all',
|
||||||
'bypass_ssl': default_conf['bypass_ssl'].lower() == 'true' if 'bypass_ssl' in default_conf else False,
|
'bypass_ssl': default_conf['bypass_ssl'].lower() == 'true' if 'bypass_ssl' in default_conf else False,
|
||||||
'file_logging': default_conf['file_logging'].lower() == 'true' if 'file_logging' in default_conf else True,
|
'file_logging': default_conf['file_logging'].lower() == 'true' if 'file_logging' in default_conf else True,
|
||||||
'default_ui': default_conf['default_ui'] if 'default_ui' in default_conf else 'none',
|
|
||||||
'component_policy': default_conf['component_policy'] if 'component_policy' in default_conf else 'workflow',
|
'component_policy': default_conf['component_policy'] if 'component_policy' in default_conf else 'workflow',
|
||||||
'windows_selector_event_loop_policy': default_conf['windows_selector_event_loop_policy'].lower() == 'true' if 'windows_selector_event_loop_policy' in default_conf else False,
|
'windows_selector_event_loop_policy': default_conf['windows_selector_event_loop_policy'].lower() == 'true' if 'windows_selector_event_loop_policy' in default_conf else False,
|
||||||
'model_download_by_agent': default_conf['model_download_by_agent'].lower() == 'true' if 'model_download_by_agent' in default_conf else False,
|
'model_download_by_agent': default_conf['model_download_by_agent'].lower() == 'true' if 'model_download_by_agent' in default_conf else False,
|
||||||
'downgrade_blacklist': default_conf['downgrade_blacklist'] if 'downgrade_blacklist' in default_conf else '',
|
'downgrade_blacklist': default_conf['downgrade_blacklist'] if 'downgrade_blacklist' in default_conf else '',
|
||||||
'skip_migration_check': default_conf['skip_migration_check'].lower() == 'true' if 'skip_migration_check' in default_conf else False,
|
'skip_migration_check': default_conf['skip_migration_check'].lower() == 'true' if 'skip_migration_check' in default_conf else False,
|
||||||
'security_level': security_level
|
'always_lazy_install': default_conf['always_lazy_install'].lower() == 'true' if 'always_lazy_install' in default_conf else False,
|
||||||
|
'security_level': security_level,
|
||||||
}
|
}
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
|
manager_util.use_uv = False
|
||||||
return {
|
return {
|
||||||
|
'http_channel_enabled': False,
|
||||||
'preview_method': manager_funcs.get_current_preview_method(),
|
'preview_method': manager_funcs.get_current_preview_method(),
|
||||||
'git_exe': '',
|
'git_exe': '',
|
||||||
|
'use_uv': False,
|
||||||
'channel_url': DEFAULT_CHANNEL,
|
'channel_url': DEFAULT_CHANNEL,
|
||||||
|
'default_cache_as_channel_url': False,
|
||||||
'share_option': 'all',
|
'share_option': 'all',
|
||||||
'bypass_ssl': False,
|
'bypass_ssl': False,
|
||||||
'file_logging': True,
|
'file_logging': True,
|
||||||
'default_ui': 'none',
|
|
||||||
'component_policy': 'workflow',
|
'component_policy': 'workflow',
|
||||||
'windows_selector_event_loop_policy': False,
|
'windows_selector_event_loop_policy': False,
|
||||||
'model_download_by_agent': False,
|
'model_download_by_agent': False,
|
||||||
'downgrade_blacklist': '',
|
'downgrade_blacklist': '',
|
||||||
'skip_migration_check': False,
|
'skip_migration_check': False,
|
||||||
|
'always_lazy_install': False,
|
||||||
'security_level': 'normal',
|
'security_level': 'normal',
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1620,6 +1633,8 @@ def get_config():
|
|||||||
|
|
||||||
if cached_config is None:
|
if cached_config is None:
|
||||||
cached_config = read_config()
|
cached_config = read_config()
|
||||||
|
if cached_config['http_channel_enabled']:
|
||||||
|
print("[ComfyUI-Manager] Warning: http channel enabled, make sure server in secure env")
|
||||||
|
|
||||||
return cached_config
|
return cached_config
|
||||||
|
|
||||||
@@ -1668,7 +1683,9 @@ def switch_to_default_branch(repo):
|
|||||||
|
|
||||||
|
|
||||||
def try_install_script(url, repo_path, install_cmd, instant_execution=False):
|
def try_install_script(url, repo_path, install_cmd, instant_execution=False):
|
||||||
if not instant_execution and ((len(install_cmd) > 0 and install_cmd[0].startswith('#')) or (platform.system() == "Windows" and comfy_ui_commit_datetime.date() >= comfy_ui_required_commit_datetime.date())):
|
if not instant_execution and (
|
||||||
|
(len(install_cmd) > 0 and install_cmd[0].startswith('#')) or platform.system() == "Windows" or get_config()['always_lazy_install']
|
||||||
|
):
|
||||||
if not os.path.exists(manager_startup_script_path):
|
if not os.path.exists(manager_startup_script_path):
|
||||||
os.makedirs(manager_startup_script_path)
|
os.makedirs(manager_startup_script_path)
|
||||||
|
|
||||||
@@ -1683,6 +1700,10 @@ def try_install_script(url, repo_path, install_cmd, instant_execution=False):
|
|||||||
if is_blacklisted(install_cmd[4]):
|
if is_blacklisted(install_cmd[4]):
|
||||||
print(f"[ComfyUI-Manager] skip black listed pip installation: '{install_cmd[4]}'")
|
print(f"[ComfyUI-Manager] skip black listed pip installation: '{install_cmd[4]}'")
|
||||||
return True
|
return True
|
||||||
|
elif len(install_cmd) == 6 and install_cmd[3:5] == ['pip', 'install']: # uv mode
|
||||||
|
if is_blacklisted(install_cmd[5]):
|
||||||
|
print(f"[ComfyUI-Manager] skip black listed pip installation: '{install_cmd[5]}'")
|
||||||
|
return True
|
||||||
|
|
||||||
print(f"\n## ComfyUI-Manager: EXECUTE => {install_cmd}")
|
print(f"\n## ComfyUI-Manager: EXECUTE => {install_cmd}")
|
||||||
code = manager_funcs.run_script(install_cmd, cwd=repo_path)
|
code = manager_funcs.run_script(install_cmd, cwd=repo_path)
|
||||||
@@ -1799,9 +1820,9 @@ def execute_install_script(url, repo_path, lazy_mode=False, instant_execution=Fa
|
|||||||
if package_name and not package_name.startswith('#'):
|
if package_name and not package_name.startswith('#'):
|
||||||
if '--index-url' in package_name:
|
if '--index-url' in package_name:
|
||||||
s = package_name.split('--index-url')
|
s = package_name.split('--index-url')
|
||||||
install_cmd = [sys.executable, "-m", "pip", "install", s[0].strip(), '--index-url', s[1].strip()]
|
install_cmd = manager_util.make_pip_cmd(["install", s[0].strip(), '--index-url', s[1].strip()])
|
||||||
else:
|
else:
|
||||||
install_cmd = [sys.executable, "-m", "pip", "install", package_name]
|
install_cmd = manager_util.make_pip_cmd(["install", package_name])
|
||||||
|
|
||||||
if package_name.strip() != "" and not package_name.startswith('#'):
|
if package_name.strip() != "" and not package_name.startswith('#'):
|
||||||
try_install_script(url, repo_path, install_cmd, instant_execution=instant_execution)
|
try_install_script(url, repo_path, install_cmd, instant_execution=instant_execution)
|
||||||
@@ -2073,14 +2094,8 @@ async def get_data_by_mode(mode, filename, channel_url=None):
|
|||||||
cache_uri = str(manager_util.simple_hash(uri))+'_'+filename
|
cache_uri = str(manager_util.simple_hash(uri))+'_'+filename
|
||||||
cache_uri = os.path.join(manager_util.cache_dir, cache_uri)
|
cache_uri = os.path.join(manager_util.cache_dir, cache_uri)
|
||||||
|
|
||||||
if mode == "cache":
|
if mode == "cache" and manager_util.is_file_created_within_one_day(cache_uri):
|
||||||
if manager_util.is_file_created_within_one_day(cache_uri):
|
|
||||||
json_obj = await manager_util.get_data(cache_uri)
|
json_obj = await manager_util.get_data(cache_uri)
|
||||||
else:
|
|
||||||
json_obj = await manager_util.get_data(uri)
|
|
||||||
with manager_util.cache_lock:
|
|
||||||
with open(cache_uri, "w", encoding='utf-8') as file:
|
|
||||||
json.dump(json_obj, file, indent=4, sort_keys=True)
|
|
||||||
else:
|
else:
|
||||||
json_obj = await manager_util.get_data(uri)
|
json_obj = await manager_util.get_data(uri)
|
||||||
with manager_util.cache_lock:
|
with manager_util.cache_lock:
|
||||||
@@ -2122,7 +2137,7 @@ def gitclone_fix(files, instant_execution=False, no_deps=False):
|
|||||||
|
|
||||||
|
|
||||||
def pip_install(packages):
|
def pip_install(packages):
|
||||||
install_cmd = ['#FORCE', sys.executable, "-m", "pip", "install", '-U'] + packages
|
install_cmd = ['#FORCE'] + manager_util.make_pip_cmd(["install", '-U']) + packages
|
||||||
try_install_script('pip install via manager', '..', install_cmd)
|
try_install_script('pip install via manager', '..', install_cmd)
|
||||||
|
|
||||||
|
|
||||||
@@ -2419,7 +2434,8 @@ def check_state_of_git_node_pack_single(item, do_fetch=False, do_update_check=Tr
|
|||||||
|
|
||||||
def get_installed_pip_packages():
|
def get_installed_pip_packages():
|
||||||
# extract pip package infos
|
# extract pip package infos
|
||||||
pips = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze'], text=True).split('\n')
|
cmd = manager_util.make_pip_cmd(['freeze'])
|
||||||
|
pips = subprocess.check_output(cmd, text=True).split('\n')
|
||||||
|
|
||||||
res = {}
|
res = {}
|
||||||
for x in pips:
|
for x in pips:
|
||||||
@@ -2835,15 +2851,18 @@ async def get_unified_total_nodes(channel, mode, regsitry_cache_mode='cache'):
|
|||||||
|
|
||||||
def populate_github_stats(node_packs, json_obj_github):
|
def populate_github_stats(node_packs, json_obj_github):
|
||||||
for k, v in node_packs.items():
|
for k, v in node_packs.items():
|
||||||
url = v['reference']
|
try:
|
||||||
if url in json_obj_github:
|
url = v['reference']
|
||||||
v['stars'] = json_obj_github[url]['stars']
|
if url in json_obj_github:
|
||||||
v['last_update'] = json_obj_github[url]['last_update']
|
v['stars'] = json_obj_github[url]['stars']
|
||||||
v['trust'] = json_obj_github[url]['author_account_age_days'] > 600
|
v['last_update'] = json_obj_github[url]['last_update']
|
||||||
else:
|
v['trust'] = json_obj_github[url]['author_account_age_days'] > 600
|
||||||
v['stars'] = -1
|
else:
|
||||||
v['last_update'] = -1
|
v['stars'] = -1
|
||||||
v['trust'] = False
|
v['last_update'] = -1
|
||||||
|
v['trust'] = False
|
||||||
|
except:
|
||||||
|
logging.error(f"[ComfyUI-Manager] DB item is broken:\n{v}")
|
||||||
|
|
||||||
|
|
||||||
def populate_favorites(node_packs, json_obj_extras):
|
def populate_favorites(node_packs, json_obj_extras):
|
||||||
|
|||||||
@@ -175,10 +175,6 @@ def set_preview_method(method):
|
|||||||
set_preview_method(core.get_config()['preview_method'])
|
set_preview_method(core.get_config()['preview_method'])
|
||||||
|
|
||||||
|
|
||||||
def set_default_ui_mode(mode):
|
|
||||||
core.get_config()['default_ui'] = mode
|
|
||||||
|
|
||||||
|
|
||||||
def set_component_policy(mode):
|
def set_component_policy(mode):
|
||||||
core.get_config()['component_policy'] = mode
|
core.get_config()['component_policy'] = mode
|
||||||
|
|
||||||
@@ -369,14 +365,19 @@ def nickname_filter(json_obj):
|
|||||||
return json_obj
|
return json_obj
|
||||||
|
|
||||||
|
|
||||||
install_queue = queue.Queue()
|
task_queue = queue.Queue()
|
||||||
install_result = {}
|
nodepack_result = {}
|
||||||
|
model_result = {}
|
||||||
|
tasks_in_progress = set()
|
||||||
|
task_worker_lock = threading.Lock()
|
||||||
|
|
||||||
async def install_worker():
|
async def task_worker():
|
||||||
global install_result
|
global task_queue
|
||||||
global install_queue
|
global nodepack_result
|
||||||
|
global model_result
|
||||||
|
global tasks_in_progress
|
||||||
|
|
||||||
async def do_install(item):
|
async def do_install(item) -> str:
|
||||||
ui_id, node_spec_str, channel, mode, skip_post_install = item
|
ui_id, node_spec_str, channel, mode, skip_post_install = item
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -384,8 +385,7 @@ async def install_worker():
|
|||||||
|
|
||||||
if node_spec is None:
|
if node_spec is None:
|
||||||
logging.error(f"Cannot resolve install target: '{node_spec_str}'")
|
logging.error(f"Cannot resolve install target: '{node_spec_str}'")
|
||||||
install_result[ui_id] = f"Cannot resolve install target: '{node_spec_str}'"
|
return f"Cannot resolve install target: '{node_spec_str}'"
|
||||||
return
|
|
||||||
|
|
||||||
node_name, version_spec, is_specified = node_spec
|
node_name, version_spec, is_specified = node_spec
|
||||||
res = await core.unified_manager.install_by_id(node_name, version_spec, channel, mode, return_postinstall=skip_post_install)
|
res = await core.unified_manager.install_by_id(node_name, version_spec, channel, mode, return_postinstall=skip_post_install)
|
||||||
@@ -393,20 +393,18 @@ async def install_worker():
|
|||||||
|
|
||||||
if res.action not in ['skip', 'enable', 'install-git', 'install-cnr', 'switch-cnr']:
|
if res.action not in ['skip', 'enable', 'install-git', 'install-cnr', 'switch-cnr']:
|
||||||
logging.error(f"[ComfyUI-Manager] Installation failed:\n{res.msg}")
|
logging.error(f"[ComfyUI-Manager] Installation failed:\n{res.msg}")
|
||||||
install_result[ui_id] = res.msg
|
return res.msg
|
||||||
return
|
|
||||||
|
|
||||||
elif not res.result:
|
elif not res.result:
|
||||||
logging.error(f"[ComfyUI-Manager] Installation failed:\n{res.msg}")
|
logging.error(f"[ComfyUI-Manager] Installation failed:\n{res.msg}")
|
||||||
install_result[ui_id] = res.msg
|
return res.msg
|
||||||
return
|
|
||||||
|
|
||||||
install_result[ui_id] = 'success'
|
return 'success'
|
||||||
except Exception:
|
except Exception:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
install_result[ui_id] = f"Installation failed:\n{node_spec_str}"
|
return f"Installation failed:\n{node_spec_str}"
|
||||||
|
|
||||||
async def do_update(item):
|
async def do_update(item) -> str:
|
||||||
ui_id, node_name, node_ver = item
|
ui_id, node_name, node_ver = item
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -415,98 +413,153 @@ async def install_worker():
|
|||||||
manager_util.clear_pip_cache()
|
manager_util.clear_pip_cache()
|
||||||
|
|
||||||
if res.result:
|
if res.result:
|
||||||
install_result[ui_id] = 'success'
|
return 'success'
|
||||||
return
|
|
||||||
|
|
||||||
logging.error(f"\nERROR: An error occurred while updating '{node_name}'.")
|
logging.error(f"\nERROR: An error occurred while updating '{node_name}'.")
|
||||||
install_result[ui_id] = f"An error occurred while updating '{node_name}'."
|
|
||||||
except Exception:
|
except Exception:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
install_result[ui_id] = f"An error occurred while updating '{node_name}'."
|
|
||||||
|
|
||||||
async def do_fix(item):
|
return f"An error occurred while updating '{node_name}'."
|
||||||
|
|
||||||
|
async def do_fix(item) -> str:
|
||||||
ui_id, node_name, node_ver = item
|
ui_id, node_name, node_ver = item
|
||||||
|
|
||||||
try:
|
try:
|
||||||
res = core.unified_manager.unified_fix(node_name, node_ver)
|
res = core.unified_manager.unified_fix(node_name, node_ver)
|
||||||
|
|
||||||
if res.result:
|
if res.result:
|
||||||
install_result[ui_id] = 'success'
|
return 'success'
|
||||||
return
|
|
||||||
else:
|
else:
|
||||||
logging.error(res.msg)
|
logging.error(res.msg)
|
||||||
|
|
||||||
logging.error(f"\nERROR: An error occurred while fixing '{node_name}@{node_ver}'.")
|
logging.error(f"\nERROR: An error occurred while fixing '{node_name}@{node_ver}'.")
|
||||||
install_result[ui_id] = f"An error occurred while fixing '{node_name}@{node_ver}'."
|
|
||||||
except Exception:
|
except Exception:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
install_result[ui_id] = f"An error occurred while fixing '{node_name}@{node_ver}'."
|
|
||||||
|
|
||||||
async def do_uninstall(item):
|
return f"An error occurred while fixing '{node_name}@{node_ver}'."
|
||||||
|
|
||||||
|
async def do_uninstall(item) -> str:
|
||||||
ui_id, node_name, is_unknown = item
|
ui_id, node_name, is_unknown = item
|
||||||
|
|
||||||
try:
|
try:
|
||||||
res = core.unified_manager.unified_uninstall(node_name, is_unknown)
|
res = core.unified_manager.unified_uninstall(node_name, is_unknown)
|
||||||
|
|
||||||
if res.result:
|
if res.result:
|
||||||
install_result[ui_id] = 'success'
|
return 'success'
|
||||||
return
|
|
||||||
|
|
||||||
logging.error(f"\nERROR: An error occurred while uninstalling '{node_name}'.")
|
logging.error(f"\nERROR: An error occurred while uninstalling '{node_name}'.")
|
||||||
install_result[ui_id] = f"An error occurred while uninstalling '{node_name}'."
|
|
||||||
except Exception:
|
except Exception:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
install_result[ui_id] = f"An error occurred while uninstalling '{node_name}'."
|
|
||||||
|
|
||||||
async def do_disable(item):
|
return f"An error occurred while uninstalling '{node_name}'."
|
||||||
|
|
||||||
|
async def do_disable(item) -> str:
|
||||||
ui_id, node_name, is_unknown = item
|
ui_id, node_name, is_unknown = item
|
||||||
|
|
||||||
try:
|
try:
|
||||||
res = core.unified_manager.unified_disable(node_name, is_unknown)
|
res = core.unified_manager.unified_disable(node_name, is_unknown)
|
||||||
|
|
||||||
if res:
|
if res:
|
||||||
install_result[ui_id] = 'success'
|
return 'success'
|
||||||
return
|
|
||||||
|
|
||||||
install_result[ui_id] = f"Failed to disable: '{node_name}'"
|
|
||||||
except Exception:
|
except Exception:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
install_result[ui_id] = f"Failed to disable: '{node_name}'"
|
|
||||||
|
return f"Failed to disable: '{node_name}'"
|
||||||
|
|
||||||
|
async def do_install_model(item) -> str:
|
||||||
|
ui_id, json_data = item
|
||||||
|
|
||||||
|
model_path = get_model_path(json_data)
|
||||||
|
model_url = json_data['url']
|
||||||
|
|
||||||
|
res = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
if model_path is not None:
|
||||||
|
logging.info(f"Install model '{json_data['name']}' from '{model_url}' into '{model_path}'")
|
||||||
|
if not core.get_config()['model_download_by_agent'] and (
|
||||||
|
model_url.startswith('https://github.com') or model_url.startswith('https://huggingface.co') or model_url.startswith('https://heibox.uni-heidelberg.de')):
|
||||||
|
model_dir = get_model_dir(json_data, True)
|
||||||
|
download_url(model_url, model_dir, filename=json_data['filename'])
|
||||||
|
if model_path.endswith('.zip'):
|
||||||
|
res = core.unzip(model_path)
|
||||||
|
else:
|
||||||
|
res = True
|
||||||
|
|
||||||
|
if res:
|
||||||
|
return 'success'
|
||||||
|
else:
|
||||||
|
res = download_url_with_agent(model_url, model_path)
|
||||||
|
if res and model_path.endswith('.zip'):
|
||||||
|
res = core.unzip(model_path)
|
||||||
|
else:
|
||||||
|
logging.error(f"Model installation error: invalid model type - {json_data['type']}")
|
||||||
|
|
||||||
|
if res:
|
||||||
|
return 'success'
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"[ERROR] {e}", file=sys.stderr)
|
||||||
|
|
||||||
|
return f"Model installation error: {model_url}"
|
||||||
|
|
||||||
stats = {}
|
stats = {}
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
done_count = len(install_result)
|
done_count = len(nodepack_result) + len(model_result)
|
||||||
total_count = done_count + install_queue.qsize()
|
total_count = done_count + task_queue.qsize()
|
||||||
|
|
||||||
if install_queue.empty():
|
if task_queue.empty():
|
||||||
logging.info(f"\n[ComfyUI-Manager] Queued works are completed.\n{stats}")
|
logging.info(f"\n[ComfyUI-Manager] Queued works are completed.\n{stats}")
|
||||||
|
|
||||||
logging.info("\nAfter restarting ComfyUI, please refresh the browser.")
|
logging.info("\nAfter restarting ComfyUI, please refresh the browser.")
|
||||||
PromptServer.instance.send_sync("cm-install-status",
|
PromptServer.instance.send_sync("cm-queue-status",
|
||||||
{'status': 'done', 'result': install_result,
|
{'status': 'done',
|
||||||
|
'nodepack_result': nodepack_result, 'model_result': model_result,
|
||||||
'total_count': total_count, 'done_count': done_count})
|
'total_count': total_count, 'done_count': done_count})
|
||||||
install_result = {}
|
nodepack_result = {}
|
||||||
install_queue = queue.Queue()
|
task_queue = queue.Queue()
|
||||||
return
|
return # terminate worker thread
|
||||||
|
|
||||||
kind, item = install_queue.get()
|
with task_worker_lock:
|
||||||
|
kind, item = task_queue.get()
|
||||||
|
tasks_in_progress.add((kind, item[0]))
|
||||||
|
|
||||||
if kind == 'install':
|
try:
|
||||||
await do_install(item)
|
if kind == 'install':
|
||||||
elif kind == 'update':
|
msg = await do_install(item)
|
||||||
await do_update(item)
|
elif kind == 'install-model':
|
||||||
elif kind == 'fix':
|
msg = await do_install_model(item)
|
||||||
await do_fix(item)
|
elif kind == 'update':
|
||||||
elif kind == 'uninstall':
|
msg = await do_update(item)
|
||||||
await do_uninstall(item)
|
elif kind == 'fix':
|
||||||
elif kind == 'disable':
|
msg = await do_fix(item)
|
||||||
await do_disable(item)
|
elif kind == 'uninstall':
|
||||||
|
msg = await do_uninstall(item)
|
||||||
|
elif kind == 'disable':
|
||||||
|
msg = await do_disable(item)
|
||||||
|
else:
|
||||||
|
msg = "Unexpected kind: " + kind
|
||||||
|
except Exception:
|
||||||
|
traceback.print_exc()
|
||||||
|
msg = f"Exception: {(kind, item)}"
|
||||||
|
|
||||||
|
with task_worker_lock:
|
||||||
|
tasks_in_progress.remove((kind, item[0]))
|
||||||
|
|
||||||
|
ui_id = item[0]
|
||||||
|
if kind == 'install-model':
|
||||||
|
model_result[ui_id] = msg
|
||||||
|
ui_target = "model_manager"
|
||||||
|
else:
|
||||||
|
nodepack_result[ui_id] = msg
|
||||||
|
ui_target = "nodepack_manager"
|
||||||
|
|
||||||
stats[kind] = stats.get(kind, 0) + 1
|
stats[kind] = stats.get(kind, 0) + 1
|
||||||
|
|
||||||
PromptServer.instance.send_sync("cm-install-status",
|
PromptServer.instance.send_sync("cm-queue-status",
|
||||||
{'status': 'in_progress', 'target': item[0],
|
{'status': 'in_progress', 'target': item[0], 'ui_target': ui_target,
|
||||||
'total_count': total_count, 'done_count': done_count})
|
'total_count': total_count, 'done_count': done_count})
|
||||||
|
|
||||||
|
|
||||||
@@ -1006,30 +1059,35 @@ async def import_fail_info(request):
|
|||||||
return web.Response(status=400)
|
return web.Response(status=400)
|
||||||
|
|
||||||
|
|
||||||
@routes.post("/customnode/reinstall")
|
@routes.post("/manager/queue/reinstall")
|
||||||
async def reinstall_custom_node(request):
|
async def reinstall_custom_node(request):
|
||||||
await uninstall_custom_node(request)
|
await uninstall_custom_node(request)
|
||||||
await install_custom_node(request)
|
await install_custom_node(request)
|
||||||
|
|
||||||
|
|
||||||
@routes.get("/customnode/queue/reset")
|
@routes.get("/manager/queue/reset")
|
||||||
async def reset_queue(request):
|
async def reset_queue(request):
|
||||||
global install_queue
|
global task_queue
|
||||||
install_queue = queue.Queue()
|
task_queue = queue.Queue()
|
||||||
return web.Response(status=200)
|
return web.Response(status=200)
|
||||||
|
|
||||||
|
|
||||||
@routes.get("/customnode/queue/count")
|
@routes.get("/manager/queue/status")
|
||||||
async def queue_count(request):
|
async def queue_count(request):
|
||||||
global install_queue
|
global task_queue
|
||||||
|
|
||||||
done_count = len(install_result)
|
with task_worker_lock:
|
||||||
total_count = done_count + install_queue.qsize()
|
done_count = len(nodepack_result) + len(model_result)
|
||||||
|
in_progress_count = len(tasks_in_progress)
|
||||||
|
total_count = done_count + in_progress_count + task_queue.qsize()
|
||||||
|
is_processing = task_worker_thread is not None and task_worker_thread.is_alive()
|
||||||
|
|
||||||
return web.json_response({'total_count': total_count, 'done_count': done_count})
|
return web.json_response({
|
||||||
|
'total_count': total_count, 'done_count': done_count, 'in_progress_count': in_progress_count,
|
||||||
|
'is_processing': is_processing})
|
||||||
|
|
||||||
|
|
||||||
@routes.post("/customnode/queue/install")
|
@routes.post("/manager/queue/install")
|
||||||
async def install_custom_node(request):
|
async def install_custom_node(request):
|
||||||
if not is_allowed_security_level('middle'):
|
if not is_allowed_security_level('middle'):
|
||||||
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
||||||
@@ -1073,22 +1131,32 @@ async def install_custom_node(request):
|
|||||||
return web.Response(status=404, text="A security error has occurred. Please check the terminal logs")
|
return web.Response(status=404, text="A security error has occurred. Please check the terminal logs")
|
||||||
|
|
||||||
install_item = json_data.get('ui_id'), node_spec_str, json_data['channel'], json_data['mode'], skip_post_install
|
install_item = json_data.get('ui_id'), node_spec_str, json_data['channel'], json_data['mode'], skip_post_install
|
||||||
install_queue.put(("install", install_item))
|
task_queue.put(("install", install_item))
|
||||||
|
|
||||||
return web.Response(status=200)
|
return web.Response(status=200)
|
||||||
|
|
||||||
|
|
||||||
@routes.get("/customnode/queue/start")
|
task_worker_thread:threading.Thread = None
|
||||||
|
|
||||||
|
@routes.get("/manager/queue/start")
|
||||||
async def queue_start(request):
|
async def queue_start(request):
|
||||||
global install_result
|
global nodepack_result
|
||||||
install_result = {}
|
global model_result
|
||||||
|
global task_worker_thread
|
||||||
|
|
||||||
threading.Thread(target=lambda: asyncio.run(install_worker())).start()
|
if task_worker_thread is not None and task_worker_thread.is_alive():
|
||||||
|
return web.Response(status=201) # already in-progress
|
||||||
|
|
||||||
|
nodepack_result = {}
|
||||||
|
model_result = {}
|
||||||
|
|
||||||
|
task_worker_thread = threading.Thread(target=lambda: asyncio.run(task_worker()))
|
||||||
|
task_worker_thread.start()
|
||||||
|
|
||||||
return web.Response(status=200)
|
return web.Response(status=200)
|
||||||
|
|
||||||
|
|
||||||
@routes.post("/customnode/queue/fix")
|
@routes.post("/manager/queue/fix")
|
||||||
async def fix_custom_node(request):
|
async def fix_custom_node(request):
|
||||||
if not is_allowed_security_level('middle'):
|
if not is_allowed_security_level('middle'):
|
||||||
logging.error(SECURITY_MESSAGE_GENERAL)
|
logging.error(SECURITY_MESSAGE_GENERAL)
|
||||||
@@ -1105,7 +1173,7 @@ async def fix_custom_node(request):
|
|||||||
node_name = os.path.basename(json_data['files'][0])
|
node_name = os.path.basename(json_data['files'][0])
|
||||||
|
|
||||||
update_item = json_data.get('ui_id'), node_name, json_data['version']
|
update_item = json_data.get('ui_id'), node_name, json_data['version']
|
||||||
install_queue.put(("fix", update_item))
|
task_queue.put(("fix", update_item))
|
||||||
|
|
||||||
return web.Response(status=200)
|
return web.Response(status=200)
|
||||||
|
|
||||||
@@ -1142,7 +1210,7 @@ async def install_custom_node_pip(request):
|
|||||||
return web.Response(status=200)
|
return web.Response(status=200)
|
||||||
|
|
||||||
|
|
||||||
@routes.post("/customnode/queue/uninstall")
|
@routes.post("/manager/queue/uninstall")
|
||||||
async def uninstall_custom_node(request):
|
async def uninstall_custom_node(request):
|
||||||
if not is_allowed_security_level('middle'):
|
if not is_allowed_security_level('middle'):
|
||||||
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
||||||
@@ -1160,12 +1228,12 @@ async def uninstall_custom_node(request):
|
|||||||
node_name = os.path.basename(json_data['files'][0])
|
node_name = os.path.basename(json_data['files'][0])
|
||||||
|
|
||||||
uninstall_item = json_data.get('ui_id'), node_name, is_unknown
|
uninstall_item = json_data.get('ui_id'), node_name, is_unknown
|
||||||
install_queue.put(("uninstall", uninstall_item))
|
task_queue.put(("uninstall", uninstall_item))
|
||||||
|
|
||||||
return web.Response(status=200)
|
return web.Response(status=200)
|
||||||
|
|
||||||
|
|
||||||
@routes.post("/customnode/queue/update")
|
@routes.post("/manager/queue/update")
|
||||||
async def update_custom_node(request):
|
async def update_custom_node(request):
|
||||||
if not is_allowed_security_level('middle'):
|
if not is_allowed_security_level('middle'):
|
||||||
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
||||||
@@ -1181,7 +1249,7 @@ async def update_custom_node(request):
|
|||||||
node_name = os.path.basename(json_data['files'][0])
|
node_name = os.path.basename(json_data['files'][0])
|
||||||
|
|
||||||
update_item = json_data.get('ui_id'), node_name, json_data['version']
|
update_item = json_data.get('ui_id'), node_name, json_data['version']
|
||||||
install_queue.put(("update", update_item))
|
task_queue.put(("update", update_item))
|
||||||
|
|
||||||
return web.Response(status=200)
|
return web.Response(status=200)
|
||||||
|
|
||||||
@@ -1232,7 +1300,7 @@ async def comfyui_switch_version(request):
|
|||||||
return web.Response(status=400)
|
return web.Response(status=400)
|
||||||
|
|
||||||
|
|
||||||
@routes.post("/customnode/queue/disable")
|
@routes.post("/manager/queue/disable")
|
||||||
async def disable_node(request):
|
async def disable_node(request):
|
||||||
json_data = await request.json()
|
json_data = await request.json()
|
||||||
|
|
||||||
@@ -1246,7 +1314,7 @@ async def disable_node(request):
|
|||||||
node_name = os.path.basename(json_data['files'][0])
|
node_name = os.path.basename(json_data['files'][0])
|
||||||
|
|
||||||
update_item = json_data.get('ui_id'), node_name, is_unknown
|
update_item = json_data.get('ui_id'), node_name, is_unknown
|
||||||
install_queue.put(("disable", update_item))
|
task_queue.put(("disable", update_item))
|
||||||
|
|
||||||
return web.Response(status=200)
|
return web.Response(status=200)
|
||||||
|
|
||||||
@@ -1264,12 +1332,10 @@ async def need_to_migrate(request):
|
|||||||
return web.Response(text=str(core.need_to_migrate), status=200)
|
return web.Response(text=str(core.need_to_migrate), status=200)
|
||||||
|
|
||||||
|
|
||||||
@routes.post("/model/install")
|
@routes.post("/manager/queue/install_model")
|
||||||
async def install_model(request):
|
async def install_model(request):
|
||||||
json_data = await request.json()
|
json_data = await request.json()
|
||||||
|
|
||||||
model_path = get_model_path(json_data)
|
|
||||||
|
|
||||||
if not is_allowed_security_level('middle'):
|
if not is_allowed_security_level('middle'):
|
||||||
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
||||||
return web.Response(status=403)
|
return web.Response(status=403)
|
||||||
@@ -1287,42 +1353,8 @@ async def install_model(request):
|
|||||||
logging.error(SECURITY_MESSAGE_NORMAL_MINUS)
|
logging.error(SECURITY_MESSAGE_NORMAL_MINUS)
|
||||||
return web.Response(status=403)
|
return web.Response(status=403)
|
||||||
|
|
||||||
def do_install():
|
install_item = json_data.get('ui_id'), json_data
|
||||||
res = False
|
task_queue.put(("install-model", install_item))
|
||||||
|
|
||||||
try:
|
|
||||||
if model_path is not None:
|
|
||||||
|
|
||||||
model_url = json_data['url']
|
|
||||||
logging.info(f"Install model '{json_data['name']}' from '{model_url}' into '{model_path}'")
|
|
||||||
if not core.get_config()['model_download_by_agent'] and (
|
|
||||||
model_url.startswith('https://github.com') or model_url.startswith('https://huggingface.co') or model_url.startswith('https://heibox.uni-heidelberg.de')):
|
|
||||||
model_dir = get_model_dir(json_data, True)
|
|
||||||
download_url(model_url, model_dir, filename=json_data['filename'])
|
|
||||||
if model_path.endswith('.zip'):
|
|
||||||
res = core.unzip(model_path)
|
|
||||||
else:
|
|
||||||
res = True
|
|
||||||
|
|
||||||
if res:
|
|
||||||
return web.json_response({}, content_type='application/json')
|
|
||||||
else:
|
|
||||||
res = download_url_with_agent(model_url, model_path)
|
|
||||||
if res and model_path.endswith('.zip'):
|
|
||||||
res = core.unzip(model_path)
|
|
||||||
else:
|
|
||||||
logging.error(f"Model installation error: invalid model type - {json_data['type']}")
|
|
||||||
|
|
||||||
if res:
|
|
||||||
return web.json_response({}, content_type='application/json')
|
|
||||||
except Exception as e:
|
|
||||||
logging.error(f"[ERROR] {e}", file=sys.stderr)
|
|
||||||
return web.Response(status=400)
|
|
||||||
|
|
||||||
# Run the installation in a thread pool
|
|
||||||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
||||||
|
|
||||||
asyncio.get_event_loop().run_in_executor(executor, do_install)
|
|
||||||
|
|
||||||
return web.Response(status=200)
|
return web.Response(status=200)
|
||||||
|
|
||||||
@@ -1338,17 +1370,6 @@ async def preview_method(request):
|
|||||||
return web.Response(status=200)
|
return web.Response(status=200)
|
||||||
|
|
||||||
|
|
||||||
@routes.get("/manager/default_ui")
|
|
||||||
async def default_ui_mode(request):
|
|
||||||
if "value" in request.rel_url.query:
|
|
||||||
set_default_ui_mode(request.rel_url.query['value'])
|
|
||||||
core.write_config()
|
|
||||||
else:
|
|
||||||
return web.Response(text=core.get_config()['default_ui'], status=200)
|
|
||||||
|
|
||||||
return web.Response(status=200)
|
|
||||||
|
|
||||||
|
|
||||||
@routes.get("/manager/component/policy")
|
@routes.get("/manager/component/policy")
|
||||||
async def component_policy(request):
|
async def component_policy(request):
|
||||||
if "value" in request.rel_url.query:
|
if "value" in request.rel_url.query:
|
||||||
@@ -1555,8 +1576,13 @@ cm_global.register_api('cm.try-install-custom-node', confirm_try_install)
|
|||||||
|
|
||||||
|
|
||||||
async def default_cache_update():
|
async def default_cache_update():
|
||||||
|
channel_url = core.get_config()['channel_url']
|
||||||
async def get_cache(filename):
|
async def get_cache(filename):
|
||||||
uri = f"{core.DEFAULT_CHANNEL}/{filename}"
|
if core.get_config()['default_cache_as_channel_url']:
|
||||||
|
uri = f"{channel_url}/{filename}"
|
||||||
|
else:
|
||||||
|
uri = f"{core.DEFAULT_CHANNEL}/{filename}"
|
||||||
|
|
||||||
cache_uri = str(manager_util.simple_hash(uri)) + '_' + filename
|
cache_uri = str(manager_util.simple_hash(uri)) + '_' + filename
|
||||||
cache_uri = os.path.join(manager_util.cache_dir, cache_uri)
|
cache_uri = os.path.join(manager_util.cache_dir, cache_uri)
|
||||||
|
|
||||||
@@ -1577,7 +1603,7 @@ async def default_cache_update():
|
|||||||
|
|
||||||
# load at least once
|
# load at least once
|
||||||
await core.unified_manager.reload('remote', dont_wait=False)
|
await core.unified_manager.reload('remote', dont_wait=False)
|
||||||
await core.unified_manager.get_custom_nodes('default', 'remote')
|
await core.unified_manager.get_custom_nodes(channel_url, 'remote')
|
||||||
|
|
||||||
logging.info("[ComfyUI-Manager] All startup tasks have been completed.")
|
logging.info("[ComfyUI-Manager] All startup tasks have been completed.")
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,14 @@ cache_lock = threading.Lock()
|
|||||||
comfyui_manager_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
comfyui_manager_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||||
cache_dir = os.path.join(comfyui_manager_path, '.cache') # This path is also updated together in **manager_core.update_user_directory**.
|
cache_dir = os.path.join(comfyui_manager_path, '.cache') # This path is also updated together in **manager_core.update_user_directory**.
|
||||||
|
|
||||||
|
use_uv = False
|
||||||
|
|
||||||
|
def make_pip_cmd(cmd):
|
||||||
|
if use_uv:
|
||||||
|
return [sys.executable, '-m', 'uv', 'pip'] + cmd
|
||||||
|
else:
|
||||||
|
return [sys.executable, '-m', 'pip'] + cmd
|
||||||
|
|
||||||
|
|
||||||
# DON'T USE StrictVersion - cannot handle pre_release version
|
# DON'T USE StrictVersion - cannot handle pre_release version
|
||||||
# try:
|
# try:
|
||||||
@@ -122,7 +130,12 @@ async def get_data(uri, silent=False):
|
|||||||
with open(uri, "r", encoding="utf-8") as f:
|
with open(uri, "r", encoding="utf-8") as f:
|
||||||
json_text = f.read()
|
json_text = f.read()
|
||||||
|
|
||||||
json_obj = json.loads(json_text)
|
try:
|
||||||
|
json_obj = json.loads(json_text)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"[ComfyUI-Manager] An error occurred while fetching '{uri}': {e}")
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
if not silent:
|
if not silent:
|
||||||
print(" [DONE]")
|
print(" [DONE]")
|
||||||
@@ -209,7 +222,7 @@ def get_installed_packages(renew=False):
|
|||||||
|
|
||||||
if renew or pip_map is None:
|
if renew or pip_map is None:
|
||||||
try:
|
try:
|
||||||
result = subprocess.check_output([sys.executable, '-m', 'pip', 'list'], universal_newlines=True)
|
result = subprocess.check_output(make_pip_cmd(['list']), universal_newlines=True)
|
||||||
|
|
||||||
pip_map = {}
|
pip_map = {}
|
||||||
for line in result.split('\n'):
|
for line in result.split('\n'):
|
||||||
@@ -260,7 +273,7 @@ class PIPFixer:
|
|||||||
if len(spec) > 0:
|
if len(spec) > 0:
|
||||||
platform = spec[1]
|
platform = spec[1]
|
||||||
else:
|
else:
|
||||||
cmd = [sys.executable, '-m', 'pip', 'install', '--force', 'torch', 'torchvision', 'torchaudio']
|
cmd = make_pip_cmd(['install', '--force', 'torch', 'torchvision', 'torchaudio'])
|
||||||
subprocess.check_output(cmd, universal_newlines=True)
|
subprocess.check_output(cmd, universal_newlines=True)
|
||||||
logging.error(cmd)
|
logging.error(cmd)
|
||||||
return
|
return
|
||||||
@@ -270,15 +283,13 @@ class PIPFixer:
|
|||||||
torch_torchvision_torchaudio_ver = torch_torchvision_torchaudio_version_map.get(torch_ver)
|
torch_torchvision_torchaudio_ver = torch_torchvision_torchaudio_version_map.get(torch_ver)
|
||||||
|
|
||||||
if torch_torchvision_torchaudio_ver is None:
|
if torch_torchvision_torchaudio_ver is None:
|
||||||
cmd = [sys.executable, '-m', 'pip', 'install', '--pre',
|
cmd = make_pip_cmd(['install', '--pre', 'torch', 'torchvision', 'torchaudio',
|
||||||
'torch', 'torchvision', 'torchaudio',
|
'--index-url', f"https://download.pytorch.org/whl/nightly/{platform}"])
|
||||||
'--index-url', f"https://download.pytorch.org/whl/nightly/{platform}"]
|
|
||||||
logging.info("[ComfyUI-Manager] restore PyTorch to nightly version")
|
logging.info("[ComfyUI-Manager] restore PyTorch to nightly version")
|
||||||
else:
|
else:
|
||||||
torchvision_ver, torchaudio_ver = torch_torchvision_torchaudio_ver
|
torchvision_ver, torchaudio_ver = torch_torchvision_torchaudio_ver
|
||||||
cmd = [sys.executable, '-m', 'pip', 'install',
|
cmd = make_pip_cmd(['install', f'torch=={torch_ver}', f'torchvision=={torchvision_ver}', f"torchaudio=={torchaudio_ver}",
|
||||||
f'torch=={torch_ver}', f'torchvision=={torchvision_ver}', f"torchaudio=={torchaudio_ver}",
|
'--index-url', f"https://download.pytorch.org/whl/{platform}"])
|
||||||
'--index-url', f"https://download.pytorch.org/whl/{platform}"]
|
|
||||||
logging.info(f"[ComfyUI-Manager] restore PyTorch to {torch_ver}+{platform}")
|
logging.info(f"[ComfyUI-Manager] restore PyTorch to {torch_ver}+{platform}")
|
||||||
|
|
||||||
subprocess.check_output(cmd, universal_newlines=True)
|
subprocess.check_output(cmd, universal_newlines=True)
|
||||||
@@ -289,7 +300,7 @@ class PIPFixer:
|
|||||||
# remove `comfy` python package
|
# remove `comfy` python package
|
||||||
try:
|
try:
|
||||||
if 'comfy' in new_pip_versions:
|
if 'comfy' in new_pip_versions:
|
||||||
cmd = [sys.executable, '-m', 'pip', 'uninstall', 'comfy']
|
cmd = make_pip_cmd(['uninstall', 'comfy'])
|
||||||
subprocess.check_output(cmd, universal_newlines=True)
|
subprocess.check_output(cmd, universal_newlines=True)
|
||||||
|
|
||||||
logging.warning("[ComfyUI-Manager] 'comfy' python package is uninstalled.\nWARN: The 'comfy' package is completely unrelated to ComfyUI and should never be installed as it causes conflicts with ComfyUI.")
|
logging.warning("[ComfyUI-Manager] 'comfy' python package is uninstalled.\nWARN: The 'comfy' package is completely unrelated to ComfyUI and should never be installed as it causes conflicts with ComfyUI.")
|
||||||
@@ -335,7 +346,7 @@ class PIPFixer:
|
|||||||
|
|
||||||
if len(targets) > 0:
|
if len(targets) > 0:
|
||||||
for x in targets:
|
for x in targets:
|
||||||
cmd = [sys.executable, '-m', 'pip', 'install', f"{x}=={versions[0].version_string}"]
|
cmd = make_pip_cmd(['install', f"{x}=={versions[0].version_string}"])
|
||||||
subprocess.check_output(cmd, universal_newlines=True)
|
subprocess.check_output(cmd, universal_newlines=True)
|
||||||
|
|
||||||
logging.info(f"[ComfyUI-Manager] 'opencv' dependencies were fixed: {targets}")
|
logging.info(f"[ComfyUI-Manager] 'opencv' dependencies were fixed: {targets}")
|
||||||
@@ -348,7 +359,8 @@ class PIPFixer:
|
|||||||
np = new_pip_versions.get('numpy')
|
np = new_pip_versions.get('numpy')
|
||||||
if np is not None:
|
if np is not None:
|
||||||
if StrictVersion(np) >= StrictVersion('2'):
|
if StrictVersion(np) >= StrictVersion('2'):
|
||||||
subprocess.check_output([sys.executable, '-m', 'pip', 'install', "numpy<2"], universal_newlines=True)
|
cmd = make_pip_cmd(['install', "numpy<2"])
|
||||||
|
subprocess.check_output(cmd , universal_newlines=True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error("[ComfyUI-Manager] Failed to restore numpy")
|
logging.error("[ComfyUI-Manager] Failed to restore numpy")
|
||||||
logging.error(e)
|
logging.error(e)
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ docStyle.innerHTML = `
|
|||||||
|
|
||||||
#cm-manager-dialog {
|
#cm-manager-dialog {
|
||||||
width: 1000px;
|
width: 1000px;
|
||||||
height: 520px;
|
height: 450px;
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
@@ -137,7 +137,7 @@ docStyle.innerHTML = `
|
|||||||
|
|
||||||
.cm-notice-board {
|
.cm-notice-board {
|
||||||
width: 290px;
|
width: 290px;
|
||||||
height: 270px;
|
height: 210px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
color: var(--input-text);
|
color: var(--input-text);
|
||||||
border: 1px solid var(--descrip-text);
|
border: 1px solid var(--descrip-text);
|
||||||
@@ -811,11 +811,15 @@ const isOutputNode = (node) => {
|
|||||||
class ManagerMenuDialog extends ComfyDialog {
|
class ManagerMenuDialog extends ComfyDialog {
|
||||||
createControlsMid() {
|
createControlsMid() {
|
||||||
let self = this;
|
let self = this;
|
||||||
|
const isElectron = 'electronAPI' in window;
|
||||||
|
|
||||||
update_comfyui_button =
|
update_comfyui_button =
|
||||||
$el("button.cm-button", {
|
$el("button.cm-button", {
|
||||||
type: "button",
|
type: "button",
|
||||||
textContent: "Update ComfyUI",
|
textContent: "Update ComfyUI",
|
||||||
|
style: {
|
||||||
|
display: isElectron ? 'none' : 'block'
|
||||||
|
},
|
||||||
onclick:
|
onclick:
|
||||||
() => updateComfyUI()
|
() => updateComfyUI()
|
||||||
});
|
});
|
||||||
@@ -824,6 +828,9 @@ class ManagerMenuDialog extends ComfyDialog {
|
|||||||
$el("button.cm-button", {
|
$el("button.cm-button", {
|
||||||
type: "button",
|
type: "button",
|
||||||
textContent: "Switch ComfyUI",
|
textContent: "Switch ComfyUI",
|
||||||
|
style: {
|
||||||
|
display: isElectron ? 'none' : 'block'
|
||||||
|
},
|
||||||
onclick:
|
onclick:
|
||||||
() => switchComfyUI()
|
() => switchComfyUI()
|
||||||
});
|
});
|
||||||
@@ -901,19 +908,6 @@ class ManagerMenuDialog extends ComfyDialog {
|
|||||||
switch_comfyui_button,
|
switch_comfyui_button,
|
||||||
fetch_updates_button,
|
fetch_updates_button,
|
||||||
|
|
||||||
$el("br", {}, []),
|
|
||||||
$el("button.cm-button", {
|
|
||||||
type: "button",
|
|
||||||
textContent: "Alternatives of A1111",
|
|
||||||
onclick:
|
|
||||||
() => {
|
|
||||||
if(!CustomNodesManager.instance) {
|
|
||||||
CustomNodesManager.instance = new CustomNodesManager(app, self);
|
|
||||||
}
|
|
||||||
CustomNodesManager.instance.show(CustomNodesManager.ShowMode.ALTERNATIVES);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
|
|
||||||
$el("br", {}, []),
|
$el("br", {}, []),
|
||||||
$el("button.cm-button-red", {
|
$el("button.cm-button-red", {
|
||||||
type: "button",
|
type: "button",
|
||||||
@@ -1008,21 +1002,6 @@ class ManagerMenuDialog extends ComfyDialog {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// default ui state
|
|
||||||
let default_ui_combo = document.createElement("select");
|
|
||||||
default_ui_combo.setAttribute("title", "Set the default state to be displayed in the main menu when the browser starts.");
|
|
||||||
default_ui_combo.className = "cm-menu-combo";
|
|
||||||
default_ui_combo.appendChild($el('option', { value: 'none', text: 'Default UI: None' }, []));
|
|
||||||
default_ui_combo.appendChild($el('option', { value: 'history', text: 'Default UI: History' }, []));
|
|
||||||
default_ui_combo.appendChild($el('option', { value: 'queue', text: 'Default UI: Queue' }, []));
|
|
||||||
api.fetchApi('/manager/default_ui')
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(data => { default_ui_combo.value = data; });
|
|
||||||
|
|
||||||
default_ui_combo.addEventListener('change', function (event) {
|
|
||||||
api.fetchApi(`/manager/default_ui?value=${event.target.value}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// share
|
// share
|
||||||
let share_combo = document.createElement("select");
|
let share_combo = document.createElement("select");
|
||||||
@@ -1085,7 +1064,6 @@ class ManagerMenuDialog extends ComfyDialog {
|
|||||||
this.datasrc_combo,
|
this.datasrc_combo,
|
||||||
channel_combo,
|
channel_combo,
|
||||||
preview_combo,
|
preview_combo,
|
||||||
default_ui_combo,
|
|
||||||
share_combo,
|
share_combo,
|
||||||
component_policy_combo,
|
component_policy_combo,
|
||||||
$el("br", {}, []),
|
$el("br", {}, []),
|
||||||
@@ -1268,10 +1246,22 @@ class ManagerMenuDialog extends ComfyDialog {
|
|||||||
this.element = $el("div.comfy-modal", { id:'cm-manager-dialog', parent: document.body }, [ content ]);
|
this.element = $el("div.comfy-modal", { id:'cm-manager-dialog', parent: document.body }, [ content ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isVisible() {
|
||||||
|
return this.element?.style?.display !== "none";
|
||||||
|
}
|
||||||
|
|
||||||
show() {
|
show() {
|
||||||
this.element.style.display = "block";
|
this.element.style.display = "block";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleVisibility() {
|
||||||
|
if (this.isVisible) {
|
||||||
|
this.close();
|
||||||
|
} else {
|
||||||
|
this.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handleWorkflowGalleryButtonClick(e) {
|
handleWorkflowGalleryButtonClick(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@@ -1389,6 +1379,41 @@ app.registerExtension({
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
commands: [
|
||||||
|
{
|
||||||
|
id: "Comfy.Manager.Menu.ToggleVisibility",
|
||||||
|
label: "Toggle Manager Menu Visibility",
|
||||||
|
icon: "mdi mdi-puzzle",
|
||||||
|
function: () => {
|
||||||
|
if (!manager_instance) {
|
||||||
|
setManagerInstance(new ManagerMenuDialog());
|
||||||
|
manager_instance.show();
|
||||||
|
} else {
|
||||||
|
manager_instance.toggleVisibility();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "Comfy.Manager.CustomNodesManager.ToggleVisibility",
|
||||||
|
label: "Toggle Custom Nodes Manager Visibility",
|
||||||
|
icon: "pi pi-server",
|
||||||
|
function: () => {
|
||||||
|
if (CustomNodesManager.instance?.isVisible) {
|
||||||
|
CustomNodesManager.instance.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!manager_instance) {
|
||||||
|
setManagerInstance(new ManagerMenuDialog());
|
||||||
|
}
|
||||||
|
if (!CustomNodesManager.instance) {
|
||||||
|
CustomNodesManager.instance = new CustomNodesManager(app, self);
|
||||||
|
}
|
||||||
|
CustomNodesManager.instance.show(CustomNodesManager.ShowMode.NORMAL);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
$el("style", {
|
$el("style", {
|
||||||
textContent: style,
|
textContent: style,
|
||||||
@@ -1583,27 +1608,3 @@ app.registerExtension({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
async function set_default_ui()
|
|
||||||
{
|
|
||||||
let res = await api.fetchApi('/manager/default_ui');
|
|
||||||
if(res.status == 200) {
|
|
||||||
let mode = await res.text();
|
|
||||||
switch(mode) {
|
|
||||||
case 'history':
|
|
||||||
app.ui.queue.hide();
|
|
||||||
app.ui.history.show();
|
|
||||||
break;
|
|
||||||
case 'queue':
|
|
||||||
app.ui.queue.show();
|
|
||||||
app.ui.history.hide();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// do nothing
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
set_default_ui();
|
|
||||||
@@ -55,6 +55,12 @@ const pageCss = `
|
|||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cn-manager .cn-manager-stop {
|
||||||
|
display: none;
|
||||||
|
background-color: #500000;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
.cn-manager .cn-manager-back {
|
.cn-manager .cn-manager-back {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -344,13 +350,14 @@ const pageHtml = `
|
|||||||
<div class="cn-manager-selection"></div>
|
<div class="cn-manager-selection"></div>
|
||||||
<div class="cn-manager-message"></div>
|
<div class="cn-manager-message"></div>
|
||||||
<div class="cn-manager-footer">
|
<div class="cn-manager-footer">
|
||||||
<button class="cn-manager-back">
|
<button class="cn-manager-back">
|
||||||
<svg class="arrow-icon" width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg class="arrow-icon" width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M2 8H18M2 8L8 2M2 8L8 14" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M2 8H18M2 8L8 2M2 8L8 14" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
</svg>
|
</svg>
|
||||||
Back
|
Back
|
||||||
</button>
|
</button>
|
||||||
<button class="cn-manager-restart">Restart</button>
|
<button class="cn-manager-restart">Restart</button>
|
||||||
|
<button class="cn-manager-stop">Stop</button>
|
||||||
<div class="cn-flex-auto"></div>
|
<div class="cn-flex-auto"></div>
|
||||||
<button class="cn-manager-check-update">Check Update</button>
|
<button class="cn-manager-check-update">Check Update</button>
|
||||||
<button class="cn-manager-check-missing">Check Missing</button>
|
<button class="cn-manager-check-missing">Check Missing</button>
|
||||||
@@ -392,7 +399,8 @@ export class CustomNodesManager {
|
|||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
|
|
||||||
api.addEventListener("cm-install-status", this.onInstallStatus);
|
api.addEventListener("cm-queue-status", this.onQueueStatus);
|
||||||
|
api.addEventListener('reconnected', this.onReconnected);
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
@@ -755,10 +763,16 @@ export class CustomNodesManager {
|
|||||||
|
|
||||||
".cn-manager-restart": {
|
".cn-manager-restart": {
|
||||||
click: () => {
|
click: () => {
|
||||||
if(rebootAPI()) {
|
this.close();
|
||||||
this.close();
|
this.manager_dialog.close();
|
||||||
this.manager_dialog.close();
|
rebootAPI();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
".cn-manager-stop": {
|
||||||
|
click: () => {
|
||||||
|
api.fetchApi('/manager/queue/reset');
|
||||||
|
infoToast('Cancel', 'Remaining tasks will stop after completing the current task.');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1271,9 +1285,9 @@ export class CustomNodesManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async installNodes(list, btn, title, selected_version) {
|
async installNodes(list, btn, title, selected_version) {
|
||||||
let stats = await api.fetchApi('/customnode/queue/count');
|
let stats = await api.fetchApi('/manager/queue/status');
|
||||||
stats = await stats.json();
|
stats = await stats.json();
|
||||||
if(stats.total_count > 0) {
|
if(stats.is_processing) {
|
||||||
customAlert(`[ComfyUI-Manager] There are already tasks in progress. Please try again after it is completed. (${stats.done_count}/${stats.total_count})`);
|
customAlert(`[ComfyUI-Manager] There are already tasks in progress. Please try again after it is completed. (${stats.done_count}/${stats.total_count})`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1304,11 +1318,13 @@ export class CustomNodesManager {
|
|||||||
let needRestart = false;
|
let needRestart = false;
|
||||||
let errorMsg = "";
|
let errorMsg = "";
|
||||||
|
|
||||||
await api.fetchApi('/customnode/queue/reset');
|
await api.fetchApi('/manager/queue/reset');
|
||||||
this.install_context = btn;
|
|
||||||
|
let target_items = [];
|
||||||
|
|
||||||
for (const hash of list) {
|
for (const hash of list) {
|
||||||
const item = this.grid.getRowItemBy("hash", hash);
|
const item = this.grid.getRowItemBy("hash", hash);
|
||||||
|
target_items.push(item);
|
||||||
|
|
||||||
if (!item) {
|
if (!item) {
|
||||||
errorMsg = `Not found custom node: ${hash}`;
|
errorMsg = `Not found custom node: ${hash}`;
|
||||||
@@ -1347,7 +1363,7 @@ export class CustomNodesManager {
|
|||||||
api_mode = 'reinstall';
|
api_mode = 'reinstall';
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await api.fetchApi(`/customnode/queue/${api_mode}`, {
|
const res = await api.fetchApi(`/manager/queue/${api_mode}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(data)
|
body: JSON.stringify(data)
|
||||||
});
|
});
|
||||||
@@ -1367,18 +1383,42 @@ export class CustomNodesManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.install_context = {btn: btn, targets: target_items};
|
||||||
|
|
||||||
if(errorMsg) {
|
if(errorMsg) {
|
||||||
this.showError(errorMsg);
|
this.showError(errorMsg);
|
||||||
show_message("Installation Error:\n"+errorMsg);
|
show_message("Installation Error:\n"+errorMsg);
|
||||||
|
|
||||||
|
// reset
|
||||||
|
for(let k in target_items) {
|
||||||
|
let item = this.install_context.targets[k];
|
||||||
|
this.grid.updateCell(item, "action");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
await api.fetchApi('/customnode/queue/start');
|
await api.fetchApi('/manager/queue/start');
|
||||||
|
this.showStop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async onInstallStatus(event) {
|
async onReconnected(event) {
|
||||||
let self = CustomNodesManager.instance;
|
let self = CustomNodesManager.instance;
|
||||||
if(event.detail.status == 'in_progress') {
|
|
||||||
|
if(self.need_restart) {
|
||||||
|
self.need_restart = false;
|
||||||
|
|
||||||
|
const confirmed = await customConfirm("To apply the changes to the node pack's installation status, you need to refresh the browser. Would you like to refresh?");
|
||||||
|
if (!confirmed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.location.reload(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async onQueueStatus(event) {
|
||||||
|
let self = CustomNodesManager.instance;
|
||||||
|
if(event.detail.status == 'in_progress' && event.detail.ui_target == 'nodepack_manager') {
|
||||||
const hash = event.detail.target;
|
const hash = event.detail.target;
|
||||||
|
|
||||||
const item = self.grid.getRowItemBy("hash", hash);
|
const item = self.grid.getRowItemBy("hash", hash);
|
||||||
@@ -1386,14 +1426,20 @@ export class CustomNodesManager {
|
|||||||
item.restart = true;
|
item.restart = true;
|
||||||
self.restartMap[item.hash] = true;
|
self.restartMap[item.hash] = true;
|
||||||
self.grid.updateCell(item, "action");
|
self.grid.updateCell(item, "action");
|
||||||
|
self.grid.setRowSelected(item, false);
|
||||||
}
|
}
|
||||||
else if(event.detail.status == 'done') {
|
else if(event.detail.status == 'done') {
|
||||||
self.onInstallCompleted(event.detail);
|
self.hideStop();
|
||||||
|
self.onQueueCompleted(event.detail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async onInstallCompleted(info) {
|
async onQueueCompleted(info) {
|
||||||
let result = info.result;
|
let result = info.nodepack_result;
|
||||||
|
|
||||||
|
if(result.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let self = CustomNodesManager.instance;
|
let self = CustomNodesManager.instance;
|
||||||
|
|
||||||
@@ -1401,7 +1447,7 @@ export class CustomNodesManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { target, label, mode } = self.install_context;
|
const { target, label, mode } = self.install_context.btn;
|
||||||
target.classList.remove("cn-btn-loading");
|
target.classList.remove("cn-btn-loading");
|
||||||
|
|
||||||
let errorMsg = "";
|
let errorMsg = "";
|
||||||
@@ -1409,11 +1455,13 @@ export class CustomNodesManager {
|
|||||||
for(let hash in result){
|
for(let hash in result){
|
||||||
let v = result[hash];
|
let v = result[hash];
|
||||||
|
|
||||||
const item = self.grid.getRowItemBy("hash", hash);
|
|
||||||
self.grid.setRowSelected(item, false);
|
|
||||||
|
|
||||||
if(v != 'success')
|
if(v != 'success')
|
||||||
errorMsg += v;
|
errorMsg += v+'\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let k in self.install_context.targets) {
|
||||||
|
let item = self.install_context.targets[k];
|
||||||
|
self.grid.updateCell(item, "action");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errorMsg) {
|
if (errorMsg) {
|
||||||
@@ -1426,7 +1474,7 @@ export class CustomNodesManager {
|
|||||||
self.showRestart();
|
self.showRestart();
|
||||||
self.showMessage(`To apply the installed/updated/disabled/enabled custom node, please restart ComfyUI. And refresh browser.`, "red");
|
self.showMessage(`To apply the installed/updated/disabled/enabled custom node, please restart ComfyUI. And refresh browser.`, "red");
|
||||||
|
|
||||||
infoToast(`[ComfyUI-Manager] All tasks in the queue have been completed.\n${info.done_count}/${info.total_count}`);
|
infoToast(`[ComfyUI-Manager] All node pack tasks in the queue have been completed.\n${info.done_count}/${info.total_count}`);
|
||||||
self.install_context = undefined;
|
self.install_context = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1808,9 +1856,9 @@ export class CustomNodesManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setDisabled(disabled) {
|
setDisabled(disabled) {
|
||||||
|
|
||||||
const $close = this.element.querySelector(".cn-manager-close");
|
const $close = this.element.querySelector(".cn-manager-close");
|
||||||
const $restart = this.element.querySelector(".cn-manager-restart");
|
const $restart = this.element.querySelector(".cn-manager-restart");
|
||||||
|
const $stop = this.element.querySelector(".cn-manager-stop");
|
||||||
|
|
||||||
const list = [
|
const list = [
|
||||||
".cn-manager-header input",
|
".cn-manager-header input",
|
||||||
@@ -1822,7 +1870,7 @@ export class CustomNodesManager {
|
|||||||
})
|
})
|
||||||
.flat()
|
.flat()
|
||||||
.filter(it => {
|
.filter(it => {
|
||||||
return it !== $close && it !== $restart;
|
return it !== $close && it !== $restart && it !== $stop;
|
||||||
});
|
});
|
||||||
|
|
||||||
list.forEach($elem => {
|
list.forEach($elem => {
|
||||||
@@ -1841,6 +1889,15 @@ export class CustomNodesManager {
|
|||||||
|
|
||||||
showRestart() {
|
showRestart() {
|
||||||
this.element.querySelector(".cn-manager-restart").style.display = "block";
|
this.element.querySelector(".cn-manager-restart").style.display = "block";
|
||||||
|
this.need_restart = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
showStop() {
|
||||||
|
this.element.querySelector(".cn-manager-stop").style.display = "block";
|
||||||
|
}
|
||||||
|
|
||||||
|
hideStop() {
|
||||||
|
this.element.querySelector(".cn-manager-stop").style.display = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
setFilter(filterValue) {
|
setFilter(filterValue) {
|
||||||
@@ -1870,4 +1927,8 @@ export class CustomNodesManager {
|
|||||||
close() {
|
close() {
|
||||||
this.element.style.display = "none";
|
this.element.style.display = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isVisible() {
|
||||||
|
return this.element?.style?.display !== "none";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
|
import { app } from "../../scripts/app.js";
|
||||||
import { $el } from "../../scripts/ui.js";
|
import { $el } from "../../scripts/ui.js";
|
||||||
import {
|
import {
|
||||||
manager_instance, rebootAPI,
|
manager_instance, rebootAPI,
|
||||||
fetchData, md5, icons
|
fetchData, md5, icons, show_message, customAlert, infoToast
|
||||||
} from "./common.js";
|
} from "./common.js";
|
||||||
|
import { api } from "../../scripts/api.js";
|
||||||
|
|
||||||
// https://cenfun.github.io/turbogrid/api.html
|
// https://cenfun.github.io/turbogrid/api.html
|
||||||
import TG from "./turbogrid.esm.js";
|
import TG from "./turbogrid.esm.js";
|
||||||
@@ -46,6 +48,18 @@ const pageCss = `
|
|||||||
background-color: var(--comfy-input-bg);
|
background-color: var(--comfy-input-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cmm-manager .cmm-manager-refresh {
|
||||||
|
display: none;
|
||||||
|
background-color: #000080;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cmm-manager .cmm-manager-stop {
|
||||||
|
display: none;
|
||||||
|
background-color: #500000;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
.cmm-manager-header {
|
.cmm-manager-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
@@ -235,7 +249,14 @@ const pageHtml = `
|
|||||||
<div class="cmm-manager-selection"></div>
|
<div class="cmm-manager-selection"></div>
|
||||||
<div class="cmm-manager-message"></div>
|
<div class="cmm-manager-message"></div>
|
||||||
<div class="cmm-manager-footer">
|
<div class="cmm-manager-footer">
|
||||||
<button class="cmm-manager-back">Back</button>
|
<button class="cmm-manager-back">
|
||||||
|
<svg class="arrow-icon" width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M2 8H18M2 8L8 2M2 8L8 14" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
Back
|
||||||
|
</button>
|
||||||
|
<button class="cmm-manager-refresh">Refresh</button>
|
||||||
|
<button class="cmm-manager-stop">Stop</button>
|
||||||
<div class="cmm-flex-auto"></div>
|
<div class="cmm-flex-auto"></div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@@ -254,6 +275,8 @@ export class ModelManager {
|
|||||||
this.keywords = '';
|
this.keywords = '';
|
||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
|
|
||||||
|
api.addEventListener("cm-queue-status", this.onQueueStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
@@ -365,12 +388,25 @@ export class ModelManager {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
".cmm-manager-refresh": {
|
||||||
|
click: () => {
|
||||||
|
app.refreshComboInNodes();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
".cmm-manager-stop": {
|
||||||
|
click: () => {
|
||||||
|
api.fetchApi('/manager/queue/reset');
|
||||||
|
infoToast('Cancel', 'Remaining tasks will stop after completing the current task.');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
".cmm-manager-back": {
|
".cmm-manager-back": {
|
||||||
click: (e) => {
|
click: (e) => {
|
||||||
this.close()
|
this.close()
|
||||||
manager_instance.show();
|
manager_instance.show();
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
Object.keys(eventsMap).forEach(selector => {
|
Object.keys(eventsMap).forEach(selector => {
|
||||||
const target = this.element.querySelector(selector);
|
const target = this.element.querySelector(selector);
|
||||||
@@ -595,17 +631,28 @@ export class ModelManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async installModels(list, btn) {
|
async installModels(list, btn) {
|
||||||
|
let stats = await api.fetchApi('/manager/queue/status');
|
||||||
|
|
||||||
|
stats = await stats.json();
|
||||||
|
if(stats.is_processing) {
|
||||||
|
customAlert(`[ComfyUI-Manager] There are already tasks in progress. Please try again after it is completed. (${stats.done_count}/${stats.total_count})`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
btn.classList.add("cmm-btn-loading");
|
btn.classList.add("cmm-btn-loading");
|
||||||
this.showLoading();
|
this.showLoading();
|
||||||
this.showError("");
|
this.showError("");
|
||||||
|
|
||||||
let needRestart = false;
|
let needRefresh = false;
|
||||||
let errorMsg = "";
|
let errorMsg = "";
|
||||||
|
|
||||||
for (const item of list) {
|
await api.fetchApi('/manager/queue/reset');
|
||||||
|
|
||||||
|
let target_items = [];
|
||||||
|
|
||||||
|
for (const item of list) {
|
||||||
this.grid.scrollRowIntoView(item);
|
this.grid.scrollRowIntoView(item);
|
||||||
|
target_items.push(item);
|
||||||
|
|
||||||
if (!this.focusInstall(item)) {
|
if (!this.focusInstall(item)) {
|
||||||
this.grid.onNextUpdated(() => {
|
this.grid.onNextUpdated(() => {
|
||||||
@@ -616,48 +663,104 @@ export class ModelManager {
|
|||||||
this.showStatus(`Install ${item.name} ...`);
|
this.showStatus(`Install ${item.name} ...`);
|
||||||
|
|
||||||
const data = item.originalData;
|
const data = item.originalData;
|
||||||
const res = await fetchData('/model/install', {
|
data.ui_id = item.hash;
|
||||||
|
|
||||||
|
const res = await api.fetchApi(`/manager/queue/install_model`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify(data)
|
body: JSON.stringify(data)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (res.status != 200) {
|
||||||
if (res.error) {
|
|
||||||
errorMsg = `Install failed: ${item.name} ${res.error.message}`;
|
errorMsg = `Install failed: ${item.name} ${res.error.message}`;
|
||||||
break;;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
needRestart = true;
|
this.install_context = {btn: btn, targets: target_items};
|
||||||
|
|
||||||
this.grid.setRowSelected(item, false);
|
if(errorMsg) {
|
||||||
|
this.showError(errorMsg);
|
||||||
|
show_message("Installation Error:\n"+errorMsg);
|
||||||
|
|
||||||
|
// reset
|
||||||
|
for (const hash of list) {
|
||||||
|
const item = this.grid.getRowItemBy("hash", hash);
|
||||||
|
this.grid.updateCell(item, "installed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
await api.fetchApi('/manager/queue/start');
|
||||||
|
this.showStop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async onQueueStatus(event) {
|
||||||
|
let self = ModelManager.instance;
|
||||||
|
|
||||||
|
if(event.detail.status == 'in_progress' && event.detail.ui_target == 'model_manager') {
|
||||||
|
const hash = event.detail.target;
|
||||||
|
|
||||||
|
const item = self.grid.getRowItemBy("hash", hash);
|
||||||
|
|
||||||
item.refresh = true;
|
item.refresh = true;
|
||||||
|
self.grid.setRowSelected(item, false);
|
||||||
item.selectable = false;
|
item.selectable = false;
|
||||||
this.grid.updateCell(item, "installed");
|
// self.grid.updateCell(item, "tg-column-select");
|
||||||
this.grid.updateCell(item, "tg-column-select");
|
self.grid.updateRow(item);
|
||||||
|
}
|
||||||
|
else if(event.detail.status == 'done') {
|
||||||
|
self.hideStop();
|
||||||
|
self.onQueueCompleted(event.detail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.showStatus(`Install ${item.name} successfully`);
|
async onQueueCompleted(info) {
|
||||||
|
let result = info.model_result;
|
||||||
|
|
||||||
|
if(result.length == 0) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.hideLoading();
|
let self = ModelManager.instance;
|
||||||
|
|
||||||
|
if(!self.install_context) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let btn = self.install_context.btn;
|
||||||
|
|
||||||
|
self.hideLoading();
|
||||||
btn.classList.remove("cmm-btn-loading");
|
btn.classList.remove("cmm-btn-loading");
|
||||||
|
|
||||||
|
let errorMsg = "";
|
||||||
|
|
||||||
|
for(let hash in result){
|
||||||
|
let v = result[hash];
|
||||||
|
|
||||||
|
if(v != 'success')
|
||||||
|
errorMsg += v + '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let k in self.install_context.targets) {
|
||||||
|
let item = self.install_context.targets[k];
|
||||||
|
self.grid.updateCell(item, "installed");
|
||||||
|
}
|
||||||
|
|
||||||
if (errorMsg) {
|
if (errorMsg) {
|
||||||
this.showError(errorMsg);
|
self.showError(errorMsg);
|
||||||
|
show_message("Installation Error:\n"+errorMsg);
|
||||||
} else {
|
} else {
|
||||||
this.showStatus(`Install ${list.length} models successfully`);
|
self.showStatus(`Install ${result.length} models successfully`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needRestart) {
|
self.showRefresh();
|
||||||
this.showMessage(`To apply the installed model, please click the 'Refresh' button on the main menu.`, "red")
|
self.showMessage(`To apply the installed model, please click the 'Refresh' button.`, "red")
|
||||||
}
|
|
||||||
|
|
||||||
|
infoToast('Tasks done', `[ComfyUI-Manager] All model downloading tasks in the queue have been completed.\n${info.done_count}/${info.total_count}`);
|
||||||
|
self.install_context = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
getModelList(models) {
|
getModelList(models) {
|
||||||
|
|
||||||
const typeMap = new Map();
|
const typeMap = new Map();
|
||||||
const baseMap = new Map();
|
const baseMap = new Map();
|
||||||
|
|
||||||
@@ -826,7 +929,7 @@ export class ModelManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showLoading() {
|
showLoading() {
|
||||||
this.setDisabled(true);
|
// this.setDisabled(true);
|
||||||
if (this.grid) {
|
if (this.grid) {
|
||||||
this.grid.showLoading();
|
this.grid.showLoading();
|
||||||
this.grid.showMask({
|
this.grid.showMask({
|
||||||
@@ -836,7 +939,7 @@ export class ModelManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hideLoading() {
|
hideLoading() {
|
||||||
this.setDisabled(false);
|
// this.setDisabled(false);
|
||||||
if (this.grid) {
|
if (this.grid) {
|
||||||
this.grid.hideLoading();
|
this.grid.hideLoading();
|
||||||
this.grid.hideMask();
|
this.grid.hideMask();
|
||||||
@@ -844,8 +947,9 @@ export class ModelManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setDisabled(disabled) {
|
setDisabled(disabled) {
|
||||||
|
|
||||||
const $close = this.element.querySelector(".cmm-manager-close");
|
const $close = this.element.querySelector(".cmm-manager-close");
|
||||||
|
const $refresh = this.element.querySelector(".cmm-manager-refresh");
|
||||||
|
const $stop = this.element.querySelector(".cmm-manager-stop");
|
||||||
|
|
||||||
const list = [
|
const list = [
|
||||||
".cmm-manager-header input",
|
".cmm-manager-header input",
|
||||||
@@ -857,7 +961,7 @@ export class ModelManager {
|
|||||||
})
|
})
|
||||||
.flat()
|
.flat()
|
||||||
.filter(it => {
|
.filter(it => {
|
||||||
return it !== $close;
|
return it !== $close && it !== $refresh && it !== $stop;
|
||||||
});
|
});
|
||||||
|
|
||||||
list.forEach($elem => {
|
list.forEach($elem => {
|
||||||
@@ -874,6 +978,18 @@ export class ModelManager {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showRefresh() {
|
||||||
|
this.element.querySelector(".cmm-manager-refresh").style.display = "block";
|
||||||
|
}
|
||||||
|
|
||||||
|
showStop() {
|
||||||
|
this.element.querySelector(".cmm-manager-stop").style.display = "block";
|
||||||
|
}
|
||||||
|
|
||||||
|
hideStop() {
|
||||||
|
this.element.querySelector(".cmm-manager-stop").style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
setKeywords(keywords = "") {
|
setKeywords(keywords = "") {
|
||||||
this.keywords = keywords;
|
this.keywords = keywords;
|
||||||
this.element.querySelector(".cmm-manager-keywords").value = keywords;
|
this.element.querySelector(".cmm-manager-keywords").value = keywords;
|
||||||
|
|||||||
@@ -11,6 +11,36 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"author": "molbal",
|
||||||
|
"title": "comfy-url-fetcher [WIP]",
|
||||||
|
"reference": "https://github.com/molbal/comfy-url-fetcher",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/molbal/comfy-url-fetcher"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Fetches URLs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "myAiLemon",
|
||||||
|
"title": "MagicAutomaticPicture [WIP]",
|
||||||
|
"reference": "https://github.com/myAiLemon/MagicAutomaticPicture",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/myAiLemon/MagicAutomaticPicture"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A comfyui node package that can generate pictures and automatically save positive prompts and eliminate unwanted prompts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "neverbiasu",
|
||||||
|
"title": "ComfyUI_Output_as_Input",
|
||||||
|
"reference": "https://github.com/a-und-b/ComfyUI_Output_as_Input",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/a-und-b/ComfyUI_Output_as_Input"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "This is a simple custom ComfyUI node that allows you to easily use recent output images as input in your workflows. It does not allow image uploads on purpose and does not require any additional dependencies.\nNOTE: The files in the repo are not organized."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "neverbiasu",
|
"author": "neverbiasu",
|
||||||
"title": "ComfyUI-DeepSeek",
|
"title": "ComfyUI-DeepSeek",
|
||||||
|
|||||||
@@ -924,6 +924,7 @@
|
|||||||
"DeepSeekImageGeneration",
|
"DeepSeekImageGeneration",
|
||||||
"DeepSeekImageUnderstanding",
|
"DeepSeekImageUnderstanding",
|
||||||
"DeepSeekModelLoader",
|
"DeepSeekModelLoader",
|
||||||
|
"LLM_Loader",
|
||||||
"OpenAICompatibleLoader"
|
"OpenAICompatibleLoader"
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
@@ -932,7 +933,8 @@
|
|||||||
],
|
],
|
||||||
"https://github.com/IfnotFr/ComfyUI-Ifnot-Pack": [
|
"https://github.com/IfnotFr/ComfyUI-Ifnot-Pack": [
|
||||||
[
|
[
|
||||||
"Face Crop"
|
"Face Crop",
|
||||||
|
"Face Crop Mouth"
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
"title_aux": "ComfyUI-Ifnot-Pack"
|
"title_aux": "ComfyUI-Ifnot-Pack"
|
||||||
@@ -1628,6 +1630,10 @@
|
|||||||
"FrameBlend",
|
"FrameBlend",
|
||||||
"ImageReferenceUpdate",
|
"ImageReferenceUpdate",
|
||||||
"ImageSelector",
|
"ImageSelector",
|
||||||
|
"KeypointsInput",
|
||||||
|
"KeypointsInputNode",
|
||||||
|
"KeypointsToPose",
|
||||||
|
"KeypointsToPoseNode",
|
||||||
"SimHashCompare",
|
"SimHashCompare",
|
||||||
"TemporalConsistency"
|
"TemporalConsistency"
|
||||||
],
|
],
|
||||||
@@ -1759,6 +1765,14 @@
|
|||||||
"title_aux": "ComfyUI-Blenderesque-Nodes [WIP]"
|
"title_aux": "ComfyUI-Blenderesque-Nodes [WIP]"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/a-und-b/ComfyUI_Output_as_Input": [
|
||||||
|
[
|
||||||
|
"OutputAsInput"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "ComfyUI_Output_as_Input"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/aiden1020/ComfyUI_Artcoder": [
|
"https://github.com/aiden1020/ComfyUI_Artcoder": [
|
||||||
[
|
[
|
||||||
"ArtCoder"
|
"ArtCoder"
|
||||||
@@ -2438,6 +2452,7 @@
|
|||||||
"PolyexponentialScheduler",
|
"PolyexponentialScheduler",
|
||||||
"PorterDuffImageComposite",
|
"PorterDuffImageComposite",
|
||||||
"Preview3D",
|
"Preview3D",
|
||||||
|
"Preview3DAnimation",
|
||||||
"PreviewAudio",
|
"PreviewAudio",
|
||||||
"PreviewImage",
|
"PreviewImage",
|
||||||
"RandomNoise",
|
"RandomNoise",
|
||||||
@@ -3317,14 +3332,15 @@
|
|||||||
[
|
[
|
||||||
"ForceMinimumBatchSize",
|
"ForceMinimumBatchSize",
|
||||||
"ImageCompositeChained",
|
"ImageCompositeChained",
|
||||||
|
"LineDetection",
|
||||||
"MangaPanelSegmentationNode",
|
"MangaPanelSegmentationNode",
|
||||||
"Mask_Fill_Region",
|
"Mask_Fill_Region",
|
||||||
"MatchImageCountToMaskCount",
|
"MatchImageCountToMaskCount",
|
||||||
"ParallaxGPUTest",
|
|
||||||
"ParallaxTest",
|
"ParallaxTest",
|
||||||
"RandomCharacterPrompts",
|
"RandomCharacterPrompts",
|
||||||
"TargetLocationCrop",
|
"TargetLocationCrop",
|
||||||
"TargetLocationPaste",
|
"TargetLocationPaste",
|
||||||
|
"Yolov8Detection",
|
||||||
"easy_parallax",
|
"easy_parallax",
|
||||||
"string_list_to_prompt_schedule"
|
"string_list_to_prompt_schedule"
|
||||||
],
|
],
|
||||||
@@ -3500,6 +3516,7 @@
|
|||||||
"Hy3DSetMeshPBRAttributes",
|
"Hy3DSetMeshPBRAttributes",
|
||||||
"Hy3DSetMeshPBRTextures",
|
"Hy3DSetMeshPBRTextures",
|
||||||
"Hy3DTorchCompileSettings",
|
"Hy3DTorchCompileSettings",
|
||||||
|
"Hy3DUploadMesh",
|
||||||
"Hy3DVAEDecode"
|
"Hy3DVAEDecode"
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
@@ -4076,6 +4093,14 @@
|
|||||||
"title_aux": "ComfyUI-FramerComfy [WIP]"
|
"title_aux": "ComfyUI-FramerComfy [WIP]"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/molbal/comfy-url-fetcher": [
|
||||||
|
[
|
||||||
|
"URL Fetcher"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "comfy-url-fetcher [WIP]"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/monate0615/ComfyUI-Affine-Transform": [
|
"https://github.com/monate0615/ComfyUI-Affine-Transform": [
|
||||||
[
|
[
|
||||||
"AffineTransform"
|
"AffineTransform"
|
||||||
@@ -4109,6 +4134,17 @@
|
|||||||
"title_aux": "ComfyUI-Claude-I2T"
|
"title_aux": "ComfyUI-Claude-I2T"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/myAiLemon/MagicAutomaticPicture": [
|
||||||
|
[
|
||||||
|
"EditableStringNode",
|
||||||
|
"IntegratedCLIPTextEncodeWithExtract",
|
||||||
|
"ProcessAndSave",
|
||||||
|
"StringConcat"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "MagicAutomaticPicture [WIP]"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/naderzare/comfyui-inodes": [
|
"https://github.com/naderzare/comfyui-inodes": [
|
||||||
[
|
[
|
||||||
"IAzureAiApi",
|
"IAzureAiApi",
|
||||||
@@ -4247,7 +4283,8 @@
|
|||||||
],
|
],
|
||||||
"https://github.com/nomcycle/ComfyUI_Cluster": [
|
"https://github.com/nomcycle/ComfyUI_Cluster": [
|
||||||
[
|
[
|
||||||
"FenceClusteredWorkflow"
|
"ClusterFanInTensorsToBatch",
|
||||||
|
"ClusterInstanceIndex"
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
"title_aux": "ComfyUI_Cluster [WIP]"
|
"title_aux": "ComfyUI_Cluster [WIP]"
|
||||||
@@ -4968,6 +5005,7 @@
|
|||||||
"FixUTF8StringNode",
|
"FixUTF8StringNode",
|
||||||
"ImageResizeNode",
|
"ImageResizeNode",
|
||||||
"ImagesToVideoNode",
|
"ImagesToVideoNode",
|
||||||
|
"LoadImageFormURLNode",
|
||||||
"LoadImageFromFolderNode",
|
"LoadImageFromFolderNode",
|
||||||
"SaveImageToFolderNode",
|
"SaveImageToFolderNode",
|
||||||
"SaveImagesToFolderNode",
|
"SaveImagesToFolderNode",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,15 @@
|
|||||||
{
|
{
|
||||||
"custom_nodes": [
|
"custom_nodes": [
|
||||||
|
{
|
||||||
|
"author": "PramaLLC",
|
||||||
|
"title": "ComfyUI BEN - Background Erase Network",
|
||||||
|
"reference": "https://github.com/PramaLLC/BEN2_ComfyUI",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/PramaLLC/BEN2_ComfyUI"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Remove backgrounds from images with [a/BEN2](https://huggingface.co/PramaLLC/BEN2) in ComfyUI\nOriginal repo: [a/https://github.com/DoctorDiffusion/ComfyUI-BEN](https://github.com/DoctorDiffusion/ComfyUI-BEN)"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "BlenderNeko",
|
"author": "BlenderNeko",
|
||||||
"title": "ltdrdata/ComfyUI_TiledKSampler",
|
"title": "ltdrdata/ComfyUI_TiledKSampler",
|
||||||
|
|||||||
@@ -11,6 +11,16 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"author": "myAiLemon",
|
||||||
|
"title": "MagicGetPromptAutomatically",
|
||||||
|
"reference": "https://github.com/myAiLemon/MagicGetPromptAutomatically",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/myAiLemon/MagicGetPromptAutomatically"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A plug-in that can automatically generate pictures and save txt files in comfyui"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "ryanontheinside",
|
"author": "ryanontheinside",
|
||||||
"title": "ComfyUI_ScavengerHunt [REMOVED]",
|
"title": "ComfyUI_ScavengerHunt [REMOVED]",
|
||||||
|
|||||||
@@ -9,6 +9,72 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"author": "AiartvnTeam",
|
||||||
|
"title": "A2V Multi Image Composite",
|
||||||
|
"id": "Aiartvn",
|
||||||
|
"reference": "https://github.com/aiartvn/A2V_Multi_Image_Composite",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/aiartvn/A2V_Multi_Image_Composite"
|
||||||
|
],
|
||||||
|
"description": "Node for compositing multiple images with interactive preview and layer management",
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"tags": ["image", "composite", "layer", "blend", "transform"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "ProGamerGov",
|
||||||
|
"title": "Preview 360 Panorama for ComfyUI",
|
||||||
|
"id": "comfyui-preview360panorama",
|
||||||
|
"reference": "https://github.com/ProGamerGov/ComfyUI_preview360panorama",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/ProGamerGov/ComfyUI_preview360panorama"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A custom ComfyUI node for interactive 360° panorama image previews. Panoramic 360 images are also sometimes known as VR photography (virtual reality), HDRI environments (ex: skyboxes), image spheres, spherical images, 360 pano, and 360 degree photos."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "amorano",
|
||||||
|
"title": "Jovi_MIDI",
|
||||||
|
"id": "jovi_midi",
|
||||||
|
"reference": "https://github.com/Amorano/Jovi_MIDI",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/Amorano/Jovi_MIDI"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Read and Process data from MIDI devices inside of ComfyUI."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "nkchocoai",
|
||||||
|
"title": "ComfyUI-DanbooruPromptQuiz",
|
||||||
|
"reference": "https://github.com/nkchocoai/ComfyUI-DanbooruPromptQuiz",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/nkchocoai/ComfyUI-DanbooruPromptQuiz"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "This node is for playing the game of guessing prompts by looking at images generated from prompts output by TIPO, Tagger, etc.."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "agilly1989",
|
||||||
|
"title": "ComfyUI_agilly1989_motorway",
|
||||||
|
"reference": "https://github.com/agilly1989/ComfyUI_agilly1989_motorway",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/agilly1989/ComfyUI_agilly1989_motorway"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "This my implemenation of a `pipe` in ComfyUI. Is it better or worse than others? No idea."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "da2el-ai",
|
||||||
|
"title": "D2-PromptSelector-comfyUI",
|
||||||
|
"reference": "https://github.com/da2el-ai/D2-PromptSelector-comfyUI",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/da2el-ai/D2-PromptSelector-comfyUI"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "This is a version of [a/sd-d2-prompt-selector](https://github.com/da2el-ai/sd-d2-prompt-selector) reworked for ComfyUI. It's just a prototype that I've put together for now. The random syntax of sd-d2-prompt-selector cannot be used; instead, the DynamicPrompt syntax is used"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "kijai",
|
"author": "kijai",
|
||||||
"title": "ComfyUI-StableXWrapper",
|
"title": "ComfyUI-StableXWrapper",
|
||||||
@@ -667,26 +733,6 @@
|
|||||||
],
|
],
|
||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "A Text To Speech node using Kokoro TTS in ComfyUI."
|
"description": "A Text To Speech node using Kokoro TTS in ComfyUI."
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "WangPengxing",
|
|
||||||
"title": "ComfyUI WPX Nodes",
|
|
||||||
"reference": "https://github.com/WangPengxing/ComfyUI_WPX_Node",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/WangPengxing/ComfyUI_WPX_Node"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "A custom node collection for ComfyUI, offering enhanced image processing features."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "PixelFunAI",
|
|
||||||
"title": "Hunyuan LoRA Loader Nodes",
|
|
||||||
"reference": "https://github.com/PixelFunAI/ComfyUI_PixelFun",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/PixelFunAI/ComfyUI_PixelFun"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "This collection provides four additional nodes for loading and managing Hunyuan Video LoRAs in ComfyUI"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -493,6 +493,7 @@
|
|||||||
"https://github.com/852wa/ComfyUI-ColorshiftColor": [
|
"https://github.com/852wa/ComfyUI-ColorshiftColor": [
|
||||||
[
|
[
|
||||||
"ColorshiftColor",
|
"ColorshiftColor",
|
||||||
|
"CsCFill",
|
||||||
"CsCPaletteEditor"
|
"CsCPaletteEditor"
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
@@ -1427,6 +1428,18 @@
|
|||||||
"title_aux": "Jovi_GLSL"
|
"title_aux": "Jovi_GLSL"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/Amorano/Jovi_MIDI": [
|
||||||
|
[
|
||||||
|
"MIDI FILTER (JOV_MIDI)",
|
||||||
|
"MIDI FILTER EZ (JOV_MIDI)",
|
||||||
|
"MIDI LOADER (JOV_MIDI)",
|
||||||
|
"MIDI MESSAGE (JOV_MIDI)",
|
||||||
|
"MIDI READER (JOV_MIDI)"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "Jovi_MIDI"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/Amorano/Jovi_Measure": [
|
"https://github.com/Amorano/Jovi_Measure": [
|
||||||
[
|
[
|
||||||
"BLUR EFFECT (JOV_MEASURE)",
|
"BLUR EFFECT (JOV_MEASURE)",
|
||||||
@@ -2818,11 +2831,17 @@
|
|||||||
],
|
],
|
||||||
"https://github.com/DesertPixelAi/ComfyUI-Desert-Pixel-Nodes": [
|
"https://github.com/DesertPixelAi/ComfyUI-Desert-Pixel-Nodes": [
|
||||||
[
|
[
|
||||||
"DP 10 String Switch",
|
"DP 10 Images Switch Or Batch",
|
||||||
|
"DP 10 String Switch Or Connect",
|
||||||
"DP 2 String Switch",
|
"DP 2 String Switch",
|
||||||
|
"DP 3 Images Switch Or Batch",
|
||||||
|
"DP 3 String Switch Or Connect",
|
||||||
"DP 5 Find And Replace",
|
"DP 5 Find And Replace",
|
||||||
"DP 5 String Switch",
|
"DP 5 Images Switch Or Batch",
|
||||||
|
"DP 5 String Switch Or Connect",
|
||||||
|
"DP Add Background To Png",
|
||||||
"DP Add Weight To String Sdxl",
|
"DP Add Weight To String Sdxl",
|
||||||
|
"DP Advanced Sampler",
|
||||||
"DP Advanced Weight String Sdxl",
|
"DP Advanced Weight String Sdxl",
|
||||||
"DP Animation Calculator 10 Inputs",
|
"DP Animation Calculator 10 Inputs",
|
||||||
"DP Animation Calculator 5 Inputs",
|
"DP Animation Calculator 5 Inputs",
|
||||||
@@ -2832,8 +2851,7 @@
|
|||||||
"DP Broken Token",
|
"DP Broken Token",
|
||||||
"DP Clean Prompt",
|
"DP Clean Prompt",
|
||||||
"DP Clean Prompt Travel",
|
"DP Clean Prompt Travel",
|
||||||
"DP Combo Controller",
|
"DP Condition Switch",
|
||||||
"DP Condition Mixer",
|
|
||||||
"DP ControlNet Apply Advanced",
|
"DP ControlNet Apply Advanced",
|
||||||
"DP Crazy Prompt Mixer",
|
"DP Crazy Prompt Mixer",
|
||||||
"DP Create Json File",
|
"DP Create Json File",
|
||||||
@@ -2845,6 +2863,7 @@
|
|||||||
"DP Fast Slow Motion",
|
"DP Fast Slow Motion",
|
||||||
"DP Five Lora",
|
"DP Five Lora",
|
||||||
"DP Five Lora Random",
|
"DP Five Lora Random",
|
||||||
|
"DP Float Stepper",
|
||||||
"DP Image And String Pairs Switch",
|
"DP Image And String Pairs Switch",
|
||||||
"DP Image Color Analyzer",
|
"DP Image Color Analyzer",
|
||||||
"DP Image Color Analyzer Small",
|
"DP Image Color Analyzer Small",
|
||||||
@@ -2855,12 +2874,10 @@
|
|||||||
"DP Image Empty Latent Switch SDXL",
|
"DP Image Empty Latent Switch SDXL",
|
||||||
"DP Image Slide Show",
|
"DP Image Slide Show",
|
||||||
"DP Image Strip",
|
"DP Image Strip",
|
||||||
"DP Image Switch 10",
|
|
||||||
"DP Image Switch 3",
|
|
||||||
"DP Image Switch 5",
|
|
||||||
"DP Int 0-1000",
|
"DP Int 0-1000",
|
||||||
"DP Int 0-1000 4 Step",
|
"DP Int 0-1000 4 Step",
|
||||||
"DP Int 0-1000 8 Step",
|
"DP Int 0-1000 8 Step",
|
||||||
|
"DP Latent Split",
|
||||||
"DP Line Cycler",
|
"DP Line Cycler",
|
||||||
"DP Load Checkpoint With Info",
|
"DP Load Checkpoint With Info",
|
||||||
"DP Load Controlnet Model With Name",
|
"DP Load Controlnet Model With Name",
|
||||||
@@ -2870,13 +2887,10 @@
|
|||||||
"DP Load Image Minimal",
|
"DP Load Image Minimal",
|
||||||
"DP Load UNET With Info",
|
"DP Load UNET With Info",
|
||||||
"DP Logo Animator",
|
"DP Logo Animator",
|
||||||
"DP Logo Animator Advanced",
|
|
||||||
"DP Lora Random Strength Controller",
|
"DP Lora Random Strength Controller",
|
||||||
"DP Lora Strength Controller",
|
"DP Lora Strength Controller",
|
||||||
"DP Lora Strength Stepper",
|
|
||||||
"DP Mask Settings",
|
"DP Mask Settings",
|
||||||
"DP Prompt Inverter",
|
"DP Prompt Inverter",
|
||||||
"DP Prompt Manager",
|
|
||||||
"DP Prompt Manager Small",
|
"DP Prompt Manager Small",
|
||||||
"DP Prompt Mode Controller",
|
"DP Prompt Mode Controller",
|
||||||
"DP Prompt Styler",
|
"DP Prompt Styler",
|
||||||
@@ -2894,9 +2908,7 @@
|
|||||||
"DP Save Preview Image",
|
"DP Save Preview Image",
|
||||||
"DP Set New Model Folder Link",
|
"DP Set New Model Folder Link",
|
||||||
"DP String Text",
|
"DP String Text",
|
||||||
"DP String Text With Weight",
|
"DP String Text With Sdxl Weight",
|
||||||
"DP String With Switch",
|
|
||||||
"DP Strings Connector",
|
|
||||||
"DP Strip Edge Masks",
|
"DP Strip Edge Masks",
|
||||||
"DP Switch Controller",
|
"DP Switch Controller",
|
||||||
"DP Text Preview",
|
"DP Text Preview",
|
||||||
@@ -2907,10 +2919,8 @@
|
|||||||
"DP Video Looper",
|
"DP Video Looper",
|
||||||
"DP Video Transition",
|
"DP Video Transition",
|
||||||
"DP_Crazy_Prompt_Mixer",
|
"DP_Crazy_Prompt_Mixer",
|
||||||
"DP_Logo_Animator_Advanced",
|
"DP_Float_Stepper",
|
||||||
"DP_Lora_Strength_Stepper",
|
"DP_Prompt_Inverter"
|
||||||
"DP_Prompt_Inverter",
|
|
||||||
"DP_Strings_Connector"
|
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
"title_aux": "ComfyUI-Desert-Pixel-Nodes"
|
"title_aux": "ComfyUI-Desert-Pixel-Nodes"
|
||||||
@@ -4714,6 +4724,8 @@
|
|||||||
],
|
],
|
||||||
"https://github.com/JTriggerFish/ComfyLatentTools": [
|
"https://github.com/JTriggerFish/ComfyLatentTools": [
|
||||||
[
|
[
|
||||||
|
"DownsampledAttentionGuidance",
|
||||||
|
"DownsampledLatentGuidance",
|
||||||
"LatentNormalizedLanczosResize",
|
"LatentNormalizedLanczosResize",
|
||||||
"RescaledPAG",
|
"RescaledPAG",
|
||||||
"RescaledSEG"
|
"RescaledSEG"
|
||||||
@@ -5018,6 +5030,7 @@
|
|||||||
[
|
[
|
||||||
"Simple Extract Lora From Text",
|
"Simple Extract Lora From Text",
|
||||||
"Simple Image Saver (as Forge)",
|
"Simple Image Saver (as Forge)",
|
||||||
|
"Simple Load Image With Metadata",
|
||||||
"Simple Load Line From Text File",
|
"Simple Load Line From Text File",
|
||||||
"Simple Lora Loader"
|
"Simple Lora Loader"
|
||||||
],
|
],
|
||||||
@@ -5841,6 +5854,7 @@
|
|||||||
],
|
],
|
||||||
"https://github.com/MNeMoNiCuZ/ComfyUI-mnemic-nodes": [
|
"https://github.com/MNeMoNiCuZ/ComfyUI-mnemic-nodes": [
|
||||||
[
|
[
|
||||||
|
"LoraTagLoader",
|
||||||
"StringCleaning",
|
"StringCleaning",
|
||||||
"TiktokenTokenizer",
|
"TiktokenTokenizer",
|
||||||
"\u26d4 Generate Negative Prompt",
|
"\u26d4 Generate Negative Prompt",
|
||||||
@@ -5848,6 +5862,7 @@
|
|||||||
"\u2728\ud83d\udcac Groq LLM API",
|
"\u2728\ud83d\udcac Groq LLM API",
|
||||||
"\u2728\ud83d\udcdd Groq ALM API - Transcribe",
|
"\u2728\ud83d\udcdd Groq ALM API - Transcribe",
|
||||||
"\u2728\ud83d\udcf7 Groq VLM API",
|
"\u2728\ud83d\udcf7 Groq VLM API",
|
||||||
|
"\ud83c\udff7\ufe0f LoRA Loader Prompt Tags",
|
||||||
"\ud83d\udcbe Save Text File With Path",
|
"\ud83d\udcbe Save Text File With Path",
|
||||||
"\ud83d\udcc1 Get File Path",
|
"\ud83d\udcc1 Get File Path",
|
||||||
"\ud83d\udd20 Tiktoken Tokenizer Info",
|
"\ud83d\udd20 Tiktoken Tokenizer Info",
|
||||||
@@ -6434,10 +6449,13 @@
|
|||||||
],
|
],
|
||||||
"https://github.com/MzMaXaM/ComfyUi-MzMaXaM": [
|
"https://github.com/MzMaXaM/ComfyUi-MzMaXaM": [
|
||||||
[
|
[
|
||||||
|
"ImageToText",
|
||||||
"KSamplerWithVAE",
|
"KSamplerWithVAE",
|
||||||
"SelectLatentSize1MP",
|
"SelectLatentSize1MP",
|
||||||
"SelectLatentSize2MP",
|
"SelectLatentSize2MP",
|
||||||
"TextEncode3in1",
|
"TextEncode3in1",
|
||||||
|
"TextToText",
|
||||||
|
"UpscaleImageBy1_5x",
|
||||||
"UpscaleLatentBy1_5x"
|
"UpscaleLatentBy1_5x"
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
@@ -7061,6 +7079,14 @@
|
|||||||
"title_aux": "ComfyUI-StringsAndThings"
|
"title_aux": "ComfyUI-StringsAndThings"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/ProGamerGov/ComfyUI_preview360panorama": [
|
||||||
|
[
|
||||||
|
"PanoramaViewerNode"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "Preview 360 Panorama for ComfyUI"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/ProGamerGov/ComfyUI_pytorch360convert": [
|
"https://github.com/ProGamerGov/ComfyUI_pytorch360convert": [
|
||||||
[
|
[
|
||||||
"Crop Image with Coords",
|
"Crop Image with Coords",
|
||||||
@@ -7351,6 +7377,7 @@
|
|||||||
"AspectRatioAdvanced",
|
"AspectRatioAdvanced",
|
||||||
"DisplayEverything",
|
"DisplayEverything",
|
||||||
"ImageComparer",
|
"ImageComparer",
|
||||||
|
"LensFlare",
|
||||||
"MultiFloat",
|
"MultiFloat",
|
||||||
"MultiTextNode",
|
"MultiTextNode",
|
||||||
"SKB_AnySwitch",
|
"SKB_AnySwitch",
|
||||||
@@ -8450,8 +8477,10 @@
|
|||||||
"SD35StartSettings",
|
"SD35StartSettings",
|
||||||
"SDXLStartSettings",
|
"SDXLStartSettings",
|
||||||
"SDstarsampler",
|
"SDstarsampler",
|
||||||
|
"Star Face Loader",
|
||||||
"StarFiveWildcards",
|
"StarFiveWildcards",
|
||||||
"StarImageSwitch",
|
"StarImageSwitch",
|
||||||
|
"StarLatentSwitch",
|
||||||
"StarTextFilter",
|
"StarTextFilter",
|
||||||
"StarTextInput",
|
"StarTextInput",
|
||||||
"Starupscale"
|
"Starupscale"
|
||||||
@@ -10646,6 +10675,18 @@
|
|||||||
"title_aux": "ComfyUI-styles-all"
|
"title_aux": "ComfyUI-styles-all"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/agilly1989/ComfyUI_agilly1989_motorway": [
|
||||||
|
[
|
||||||
|
"MotorwayFloat",
|
||||||
|
"MotorwayInt",
|
||||||
|
"MotorwaySeed",
|
||||||
|
"MotorwayStr",
|
||||||
|
"MotorwayStrMulti"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "ComfyUI_agilly1989_motorway"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/ahernandezmiro/ComfyUI-GCP_Storage_tools": [
|
"https://github.com/ahernandezmiro/ComfyUI-GCP_Storage_tools": [
|
||||||
[
|
[
|
||||||
"GCPReadImageNode",
|
"GCPReadImageNode",
|
||||||
@@ -10721,6 +10762,14 @@
|
|||||||
"title_aux": "Comfy UI FatLabels"
|
"title_aux": "Comfy UI FatLabels"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/aiartvn/A2V_Multi_Image_Composite": [
|
||||||
|
[
|
||||||
|
"A2V_Multi_Image_Composite"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "A2V Multi Image Composite"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/aidec/Comfyui_TextBatch_aidec": [
|
"https://github.com/aidec/Comfyui_TextBatch_aidec": [
|
||||||
[
|
[
|
||||||
"ImageQueueProcessor",
|
"ImageQueueProcessor",
|
||||||
@@ -11881,18 +11930,22 @@
|
|||||||
"SamplerSonarEuler",
|
"SamplerSonarEuler",
|
||||||
"SamplerSonarEulerA",
|
"SamplerSonarEulerA",
|
||||||
"SonarAdvanced1fNoise",
|
"SonarAdvanced1fNoise",
|
||||||
|
"SonarAdvancedDistroNoise",
|
||||||
"SonarAdvancedPowerLawNoise",
|
"SonarAdvancedPowerLawNoise",
|
||||||
"SonarAdvancedPyramidNoise",
|
"SonarAdvancedPyramidNoise",
|
||||||
"SonarBlendedNoise",
|
"SonarBlendedNoise",
|
||||||
"SonarChannelNoise",
|
"SonarChannelNoise",
|
||||||
"SonarCompositeNoise",
|
"SonarCompositeNoise",
|
||||||
"SonarCustomNoise",
|
"SonarCustomNoise",
|
||||||
|
"SonarCustomNoiseAdv",
|
||||||
"SonarGuidanceConfig",
|
"SonarGuidanceConfig",
|
||||||
"SonarGuidedNoise",
|
"SonarGuidedNoise",
|
||||||
"SonarModulatedNoise",
|
"SonarModulatedNoise",
|
||||||
"SonarRandomNoise",
|
"SonarRandomNoise",
|
||||||
"SonarRepeatedNoise",
|
"SonarRepeatedNoise",
|
||||||
"SonarScheduledNoise"
|
"SonarResizedNoise",
|
||||||
|
"SonarScheduledNoise",
|
||||||
|
"SonarWaveletFilteredNoise"
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
"title_aux": "ComfyUI-sonar"
|
"title_aux": "ComfyUI-sonar"
|
||||||
@@ -13897,6 +13950,7 @@
|
|||||||
"PolyexponentialScheduler",
|
"PolyexponentialScheduler",
|
||||||
"PorterDuffImageComposite",
|
"PorterDuffImageComposite",
|
||||||
"Preview3D",
|
"Preview3D",
|
||||||
|
"Preview3DAnimation",
|
||||||
"PreviewAudio",
|
"PreviewAudio",
|
||||||
"PreviewImage",
|
"PreviewImage",
|
||||||
"RandomNoise",
|
"RandomNoise",
|
||||||
@@ -15452,7 +15506,8 @@
|
|||||||
"SelOutModel",
|
"SelOutModel",
|
||||||
"SelOutPolar",
|
"SelOutPolar",
|
||||||
"Selector",
|
"Selector",
|
||||||
"Selector Advanced"
|
"Selector Advanced",
|
||||||
|
"Selector Hub"
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
"author": "\"\u02f6\ud835\udfa2\u292c\u2ad2\u2d56s\u143c\u02f6\"",
|
"author": "\"\u02f6\ud835\udfa2\u292c\u2ad2\u2d56s\u143c\u02f6\"",
|
||||||
@@ -16638,8 +16693,10 @@
|
|||||||
"Griptape Replace: Rulesets on Agent",
|
"Griptape Replace: Rulesets on Agent",
|
||||||
"Griptape Replace: Tools on Agent",
|
"Griptape Replace: Tools on Agent",
|
||||||
"Griptape Rerank Driver: Cohere",
|
"Griptape Rerank Driver: Cohere",
|
||||||
|
"Griptape Retrieve: Cloud Ruleset",
|
||||||
"Griptape Run: Agent",
|
"Griptape Run: Agent",
|
||||||
"Griptape Run: Audio Transcription",
|
"Griptape Run: Audio Transcription",
|
||||||
|
"Griptape Run: Cloud Assistant",
|
||||||
"Griptape Run: Image Description",
|
"Griptape Run: Image Description",
|
||||||
"Griptape Run: Parallel Image Description",
|
"Griptape Run: Parallel Image Description",
|
||||||
"Griptape Run: Prompt Task",
|
"Griptape Run: Prompt Task",
|
||||||
@@ -19306,6 +19363,7 @@
|
|||||||
"GetImageRangeFromBatch",
|
"GetImageRangeFromBatch",
|
||||||
"GetImageSizeAndCount",
|
"GetImageSizeAndCount",
|
||||||
"GetImagesFromBatchIndexed",
|
"GetImagesFromBatchIndexed",
|
||||||
|
"GetLatentRangeFromBatch",
|
||||||
"GetLatentsFromBatchIndexed",
|
"GetLatentsFromBatchIndexed",
|
||||||
"GetMaskSizeAndCount",
|
"GetMaskSizeAndCount",
|
||||||
"GradientToFloat",
|
"GradientToFloat",
|
||||||
@@ -19324,6 +19382,7 @@
|
|||||||
"ImageGridComposite2x2",
|
"ImageGridComposite2x2",
|
||||||
"ImageGridComposite3x3",
|
"ImageGridComposite3x3",
|
||||||
"ImageGridtoBatch",
|
"ImageGridtoBatch",
|
||||||
|
"ImageNoiseAugmentation",
|
||||||
"ImageNormalize_Neg1_To_1",
|
"ImageNormalize_Neg1_To_1",
|
||||||
"ImagePadForOutpaintMasked",
|
"ImagePadForOutpaintMasked",
|
||||||
"ImagePadForOutpaintTargetSize",
|
"ImagePadForOutpaintTargetSize",
|
||||||
@@ -19339,6 +19398,7 @@
|
|||||||
"Intrinsic_lora_sampling",
|
"Intrinsic_lora_sampling",
|
||||||
"JoinStringMulti",
|
"JoinStringMulti",
|
||||||
"JoinStrings",
|
"JoinStrings",
|
||||||
|
"LeapfusionHunyuanI2VPatcher",
|
||||||
"LoadAndResizeImage",
|
"LoadAndResizeImage",
|
||||||
"LoadImagesFromFolderKJ",
|
"LoadImagesFromFolderKJ",
|
||||||
"LoadResAdapterNormalization",
|
"LoadResAdapterNormalization",
|
||||||
@@ -20733,6 +20793,7 @@
|
|||||||
"Enhanced Random Light Source",
|
"Enhanced Random Light Source",
|
||||||
"Float Relay",
|
"Float Relay",
|
||||||
"HLFrequencyDetailRestore",
|
"HLFrequencyDetailRestore",
|
||||||
|
"Hex to Color",
|
||||||
"Image Add Alpha",
|
"Image Add Alpha",
|
||||||
"Image Frequency Analyzer",
|
"Image Frequency Analyzer",
|
||||||
"Image Relay",
|
"Image Relay",
|
||||||
@@ -22574,6 +22635,15 @@
|
|||||||
"title_aux": "ComfyUI OpenAI Prompter"
|
"title_aux": "ComfyUI OpenAI Prompter"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/nkchocoai/ComfyUI-DanbooruPromptQuiz": [
|
||||||
|
[
|
||||||
|
"DanbooruPromptComparison",
|
||||||
|
"DanbooruPromptQuiz"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "ComfyUI-DanbooruPromptQuiz"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/nkchocoai/ComfyUI-Dart": [
|
"https://github.com/nkchocoai/ComfyUI-Dart": [
|
||||||
[
|
[
|
||||||
"DanbooruTagsTransformerBanTagsFromRegex",
|
"DanbooruTagsTransformerBanTagsFromRegex",
|
||||||
@@ -22679,11 +22749,11 @@
|
|||||||
],
|
],
|
||||||
"https://github.com/nofunstudio/Node_Fun_ComfyUI": [
|
"https://github.com/nofunstudio/Node_Fun_ComfyUI": [
|
||||||
[
|
[
|
||||||
|
"IframeView",
|
||||||
"LayeredInfiniteZoom",
|
"LayeredInfiniteZoom",
|
||||||
"Replicate flux 1.1 pro ultra",
|
"Replicate flux 1.1 pro ultra",
|
||||||
"ReplicateAPI_flux_1_1_pro_ultra",
|
"ReplicateAPI_flux_1_1_pro_ultra",
|
||||||
"ReplicateAPI_flux_fill_pro",
|
"ReplicateAPI_flux_fill_pro"
|
||||||
"WebViewer"
|
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
"title_aux": "Node_Fun_ComfyUI"
|
"title_aux": "Node_Fun_ComfyUI"
|
||||||
@@ -26163,6 +26233,7 @@
|
|||||||
"quadmoonChangeBackground",
|
"quadmoonChangeBackground",
|
||||||
"quadmoonConvertBoolToString",
|
"quadmoonConvertBoolToString",
|
||||||
"quadmoonConvertFloatToString",
|
"quadmoonConvertFloatToString",
|
||||||
|
"quadmoonConvertImageToPrompt",
|
||||||
"quadmoonConvertIntToString",
|
"quadmoonConvertIntToString",
|
||||||
"quadmoonConvertNormalizeHW",
|
"quadmoonConvertNormalizeHW",
|
||||||
"quadmoonConvertNumberToString",
|
"quadmoonConvertNumberToString",
|
||||||
@@ -27139,6 +27210,7 @@
|
|||||||
],
|
],
|
||||||
"https://github.com/xlinx/ComfyUI-decadetw-auto-prompt-llm": [
|
"https://github.com/xlinx/ComfyUI-decadetw-auto-prompt-llm": [
|
||||||
[
|
[
|
||||||
|
"Auto-LLM-Chat",
|
||||||
"Auto-LLM-Text",
|
"Auto-LLM-Text",
|
||||||
"Auto-LLM-Text-Vision",
|
"Auto-LLM-Text-Vision",
|
||||||
"Auto-LLM-Vision"
|
"Auto-LLM-Vision"
|
||||||
|
|||||||
@@ -57,22 +57,6 @@ def is_import_failed_extension(name):
|
|||||||
return name in import_failed_extensions
|
return name in import_failed_extensions
|
||||||
|
|
||||||
|
|
||||||
def check_file_logging():
|
|
||||||
global enable_file_logging
|
|
||||||
try:
|
|
||||||
import configparser
|
|
||||||
config = configparser.ConfigParser()
|
|
||||||
config.read(manager_config_path)
|
|
||||||
default_conf = config['default']
|
|
||||||
|
|
||||||
if 'file_logging' in default_conf and default_conf['file_logging'].lower() == 'false':
|
|
||||||
enable_file_logging = False
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
check_file_logging()
|
|
||||||
|
|
||||||
comfy_path = os.environ.get('COMFYUI_PATH')
|
comfy_path = os.environ.get('COMFYUI_PATH')
|
||||||
comfy_base_path = os.environ.get('COMFYUI_FOLDERS_BASE_PATH')
|
comfy_base_path = os.environ.get('COMFYUI_FOLDERS_BASE_PATH')
|
||||||
|
|
||||||
@@ -103,6 +87,32 @@ manager_config_path = os.path.join(manager_files_path, 'config.ini')
|
|||||||
cm_cli_path = os.path.join(comfyui_manager_path, "cm-cli.py")
|
cm_cli_path = os.path.join(comfyui_manager_path, "cm-cli.py")
|
||||||
|
|
||||||
|
|
||||||
|
default_conf = {}
|
||||||
|
|
||||||
|
def read_config():
|
||||||
|
global default_conf
|
||||||
|
try:
|
||||||
|
import configparser
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
config.read(manager_config_path)
|
||||||
|
default_conf = config['default']
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def read_uv_mode():
|
||||||
|
if 'use_uv' in default_conf:
|
||||||
|
manager_util.use_uv = default_conf['use_uv'].lower() == 'true'
|
||||||
|
|
||||||
|
def check_file_logging():
|
||||||
|
global enable_file_logging
|
||||||
|
if 'file_logging' in default_conf and default_conf['file_logging'].lower() == 'false':
|
||||||
|
enable_file_logging = False
|
||||||
|
|
||||||
|
|
||||||
|
read_config()
|
||||||
|
read_uv_mode()
|
||||||
|
check_file_logging()
|
||||||
|
|
||||||
cm_global.pip_overrides = {'numpy': 'numpy<2', 'ultralytics': 'ultralytics==8.3.40'}
|
cm_global.pip_overrides = {'numpy': 'numpy<2', 'ultralytics': 'ultralytics==8.3.40'}
|
||||||
if os.path.exists(manager_pip_overrides_path):
|
if os.path.exists(manager_pip_overrides_path):
|
||||||
with open(manager_pip_overrides_path, 'r', encoding="UTF-8", errors="ignore") as json_file:
|
with open(manager_pip_overrides_path, 'r', encoding="UTF-8", errors="ignore") as json_file:
|
||||||
@@ -411,19 +421,20 @@ except Exception as e:
|
|||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import git # noqa: F401
|
import git # noqa: F401
|
||||||
import toml # noqa: F401
|
import toml # noqa: F401
|
||||||
|
import rich # noqa: F401
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
my_path = os.path.dirname(__file__)
|
my_path = os.path.dirname(__file__)
|
||||||
requirements_path = os.path.join(my_path, "requirements.txt")
|
requirements_path = os.path.join(my_path, "requirements.txt")
|
||||||
|
|
||||||
print("## ComfyUI-Manager: installing dependencies. (GitPython)")
|
print("## ComfyUI-Manager: installing dependencies. (GitPython)")
|
||||||
try:
|
try:
|
||||||
result = subprocess.check_output([sys.executable, '-s', '-m', 'pip', 'install', '-r', requirements_path])
|
result = subprocess.check_output(manager_util.make_pip_cmd(['install', '-r', requirements_path]))
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
print("## [ERROR] ComfyUI-Manager: Attempting to reinstall dependencies using an alternative method.")
|
print("## [ERROR] ComfyUI-Manager: Attempting to reinstall dependencies using an alternative method.")
|
||||||
try:
|
try:
|
||||||
result = subprocess.check_output([sys.executable, '-s', '-m', 'pip', 'install', '--user', '-r', requirements_path])
|
result = subprocess.check_output(manager_util.make_pip_cmd(['install', '--user', '-r', requirements_path]))
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
print("## [ERROR] ComfyUI-Manager: Failed to install the GitPython package in the correct Python environment. Please install it manually in the appropriate environment. (You can seek help at https://app.element.io/#/room/%23comfyui_space%3Amatrix.org)")
|
print("## [ERROR] ComfyUI-Manager: Failed to install the GitPython package in the correct Python environment. Please install it manually in the appropriate environment. (You can seek help at https://app.element.io/#/room/%23comfyui_space%3Amatrix.org)")
|
||||||
|
|
||||||
@@ -452,11 +463,6 @@ else:
|
|||||||
|
|
||||||
def read_downgrade_blacklist():
|
def read_downgrade_blacklist():
|
||||||
try:
|
try:
|
||||||
import configparser
|
|
||||||
config = configparser.ConfigParser()
|
|
||||||
config.read(manager_config_path)
|
|
||||||
default_conf = config['default']
|
|
||||||
|
|
||||||
if 'downgrade_blacklist' in default_conf:
|
if 'downgrade_blacklist' in default_conf:
|
||||||
items = default_conf['downgrade_blacklist'].split(',')
|
items = default_conf['downgrade_blacklist'].split(',')
|
||||||
items = [x.strip() for x in items if x != '']
|
items = [x.strip() for x in items if x != '']
|
||||||
@@ -471,19 +477,13 @@ read_downgrade_blacklist()
|
|||||||
|
|
||||||
def check_bypass_ssl():
|
def check_bypass_ssl():
|
||||||
try:
|
try:
|
||||||
import configparser
|
|
||||||
import ssl
|
import ssl
|
||||||
config = configparser.ConfigParser()
|
|
||||||
config.read(manager_config_path)
|
|
||||||
default_conf = config['default']
|
|
||||||
|
|
||||||
if 'bypass_ssl' in default_conf and default_conf['bypass_ssl'].lower() == 'true':
|
if 'bypass_ssl' in default_conf and default_conf['bypass_ssl'].lower() == 'true':
|
||||||
print(f"[ComfyUI-Manager] WARN: Unsafe - SSL verification bypass option is Enabled. (see {manager_config_path})")
|
print(f"[ComfyUI-Manager] WARN: Unsafe - SSL verification bypass option is Enabled. (see {manager_config_path})")
|
||||||
ssl._create_default_https_context = ssl._create_unverified_context # SSL certificate error fix.
|
ssl._create_default_https_context = ssl._create_unverified_context # SSL certificate error fix.
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
check_bypass_ssl()
|
check_bypass_ssl()
|
||||||
|
|
||||||
|
|
||||||
@@ -603,9 +603,9 @@ def execute_lazy_install_script(repo_path, executable):
|
|||||||
if package_name and not is_installed(package_name):
|
if package_name and not is_installed(package_name):
|
||||||
if '--index-url' in package_name:
|
if '--index-url' in package_name:
|
||||||
s = package_name.split('--index-url')
|
s = package_name.split('--index-url')
|
||||||
install_cmd = [sys.executable, "-m", "pip", "install", s[0].strip(), '--index-url', s[1].strip()]
|
install_cmd = manager_util.make_pip_cmd(["install", s[0].strip(), '--index-url', s[1].strip()])
|
||||||
else:
|
else:
|
||||||
install_cmd = [sys.executable, "-m", "pip", "install", package_name]
|
install_cmd = manager_util.make_pip_cmd(["install", package_name])
|
||||||
|
|
||||||
process_wrap(install_cmd, repo_path)
|
process_wrap(install_cmd, repo_path)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "comfyui-manager"
|
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."
|
description = "ComfyUI-Manager provides features to install and manage custom nodes for ComfyUI, as well as various functionalities to assist with ComfyUI."
|
||||||
version = "3.12.2"
|
version = "3.17.7"
|
||||||
license = { file = "LICENSE.txt" }
|
license = { file = "LICENSE.txt" }
|
||||||
dependencies = ["GitPython", "PyGithub", "matrix-client==0.4.0", "transformers", "huggingface-hub>0.20", "typer", "rich", "typing-extensions"]
|
dependencies = ["GitPython", "PyGithub", "matrix-client==0.4.0", "transformers", "huggingface-hub>0.20", "typer", "rich", "typing-extensions"]
|
||||||
|
|
||||||
|
|||||||
@@ -7,3 +7,4 @@ typer
|
|||||||
rich
|
rich
|
||||||
typing-extensions
|
typing-extensions
|
||||||
toml
|
toml
|
||||||
|
uv
|
||||||
|
|||||||
Reference in New Issue
Block a user