Compare commits
27 Commits
feat/cache
...
draft-v4-a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78269f6467 | ||
|
|
a9fedc0487 | ||
|
|
abfd85602e | ||
|
|
1816bb748e | ||
|
|
05ceab68f8 | ||
|
|
46a37907e6 | ||
|
|
7fc8ba587e | ||
|
|
7a35bd9d9a | ||
|
|
17e5c3d2f5 | ||
|
|
27bfc539f7 | ||
|
|
a76ef49d2d | ||
|
|
bb0fcf6ea6 | ||
|
|
539e0a1534 | ||
|
|
aaae6ce304 | ||
|
|
821fded09d | ||
|
|
ec4a2aa873 | ||
|
|
d6b2d54f3f | ||
|
|
97ae67bb9a | ||
|
|
765514a33f | ||
|
|
e2cdcc96c4 | ||
|
|
dbd25b0f0a | ||
|
|
a128baf894 | ||
|
|
57b847eebf | ||
|
|
149257e4f1 | ||
|
|
212b8e7ed2 | ||
|
|
01ac9c895a | ||
|
|
ebcb14e6aa |
1
.env.example
Normal file
1
.env.example
Normal file
@@ -0,0 +1 @@
|
||||
PYPI_TOKEN=your-pypi-token
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -19,4 +19,5 @@ pip_overrides.json
|
||||
check2.sh
|
||||
/venv/
|
||||
build
|
||||
*.egg-info
|
||||
*.egg-info
|
||||
.env
|
||||
47
CONTRIBUTING.md
Normal file
47
CONTRIBUTING.md
Normal file
@@ -0,0 +1,47 @@
|
||||
## Testing Changes
|
||||
|
||||
1. Activate the ComfyUI environment.
|
||||
|
||||
2. Build package locally after making changes.
|
||||
|
||||
```bash
|
||||
# from inside the ComfyUI-Manager directory, with the ComfyUI environment activated
|
||||
python -m build
|
||||
```
|
||||
|
||||
3. Install the package locally in the ComfyUI environment.
|
||||
|
||||
```bash
|
||||
# Uninstall existing package
|
||||
pip uninstall comfyui-manager
|
||||
|
||||
# Install the locale package
|
||||
pip install dist/comfyui-manager-*.whl
|
||||
```
|
||||
|
||||
4. Start ComfyUI.
|
||||
|
||||
```bash
|
||||
# after navigating to the ComfyUI directory
|
||||
python main.py
|
||||
```
|
||||
|
||||
## Manually Publish Test Version to PyPi
|
||||
|
||||
1. Set the `PYPI_TOKEN` environment variable in env file.
|
||||
|
||||
2. If manually publishing, you likely want to use a release candidate version, so set the version in [pyproject.toml](pyproject.toml) to something like `0.0.1rc1`.
|
||||
|
||||
3. Build the package.
|
||||
|
||||
```bash
|
||||
python -m build
|
||||
```
|
||||
|
||||
4. Upload the package to PyPi.
|
||||
|
||||
```bash
|
||||
python -m twine upload dist/* --username __token__ --password $PYPI_TOKEN
|
||||
```
|
||||
|
||||
5. View at https://pypi.org/project/comfyui-manager/
|
||||
@@ -4,4 +4,10 @@ include comfyui_manager/glob/*
|
||||
include LICENSE.txt
|
||||
include README.md
|
||||
include requirements.txt
|
||||
include pyproject.toml
|
||||
include pyproject.toml
|
||||
include custom-node-list.json
|
||||
include extension-node-list.json
|
||||
include extras.json
|
||||
include github-stats.json
|
||||
include model-list.json
|
||||
include alter-list.json
|
||||
@@ -2,8 +2,6 @@ import os
|
||||
import logging
|
||||
from comfy.cli_args import args
|
||||
|
||||
ENABLE_LEGACY_COMFYUI_MANAGER_FRONT_DEFAULT = True # Enable legacy ComfyUI Manager frontend while new UI is in beta phase
|
||||
|
||||
def prestartup():
|
||||
from . import prestartup_script # noqa: F401
|
||||
logging.info('[PRE] ComfyUI-Manager')
|
||||
@@ -11,14 +9,35 @@ def prestartup():
|
||||
|
||||
def start():
|
||||
logging.info('[START] ComfyUI-Manager')
|
||||
from .glob import manager_server # noqa: F401
|
||||
from .glob import share_3rdparty # noqa: F401
|
||||
from .glob import cm_global # noqa: F401
|
||||
from .common import cm_global # noqa: F401
|
||||
|
||||
should_show_legacy_manager_front = os.environ.get('ENABLE_LEGACY_COMFYUI_MANAGER_FRONT', 'false') == 'true' or ENABLE_LEGACY_COMFYUI_MANAGER_FRONT_DEFAULT
|
||||
if not args.disable_manager and should_show_legacy_manager_front:
|
||||
try:
|
||||
import nodes
|
||||
nodes.EXTENSION_WEB_DIRS['comfyui-manager-legacy'] = os.path.join(os.path.dirname(__file__), 'js')
|
||||
except Exception as e:
|
||||
print("Error enabling legacy ComfyUI Manager frontend:", e)
|
||||
if not args.disable_manager:
|
||||
if args.enable_manager_legacy_ui:
|
||||
try:
|
||||
from .legacy import manager_server # noqa: F401
|
||||
from .legacy import share_3rdparty # noqa: F401
|
||||
import nodes
|
||||
|
||||
logging.info("[ComfyUI-Manager] Legacy UI is enabled.")
|
||||
nodes.EXTENSION_WEB_DIRS['comfyui-manager-legacy'] = os.path.join(os.path.dirname(__file__), 'js')
|
||||
except Exception as e:
|
||||
print("Error enabling legacy ComfyUI Manager frontend:", e)
|
||||
else:
|
||||
from .glob import manager_server # noqa: F401
|
||||
from .glob import share_3rdparty # noqa: F401
|
||||
|
||||
|
||||
def should_be_disabled(fullpath:str) -> bool:
|
||||
"""
|
||||
1. Disables the legacy ComfyUI-Manager.
|
||||
2. The blocklist can be expanded later based on policies.
|
||||
"""
|
||||
|
||||
if not args.disable_manager:
|
||||
# In cases where installation is done via a zip archive, the directory name may not be comfyui-manager, and it may not contain a git repository.
|
||||
# It is assumed that any installed legacy ComfyUI-Manager will have at least 'comfyui-manager' in its directory name.
|
||||
dir_name = os.path.basename(fullpath).lower()
|
||||
if 'comfyui-manager' in dir_name:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@@ -15,7 +15,7 @@ import git
|
||||
import importlib
|
||||
|
||||
|
||||
import manager_util
|
||||
from .common import manager_util
|
||||
|
||||
# read env vars
|
||||
# COMFYUI_FOLDERS_BASE_PATH is not required in cm-cli.py
|
||||
@@ -35,10 +35,11 @@ if not os.path.exists(os.path.join(comfy_path, 'folder_paths.py')):
|
||||
|
||||
|
||||
import utils.extra_config
|
||||
from .glob import cm_global
|
||||
from .common import cm_global
|
||||
from .glob import manager_core as core
|
||||
from .common import context
|
||||
from .glob.manager_core import unified_manager
|
||||
from .glob import cnr_utils
|
||||
from .common import cnr_utils
|
||||
|
||||
comfyui_manager_path = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
@@ -80,7 +81,7 @@ def read_downgrade_blacklist():
|
||||
try:
|
||||
import configparser
|
||||
config = configparser.ConfigParser(strict=False)
|
||||
config.read(core.manager_config.path)
|
||||
config.read(context.manager_config_path)
|
||||
default_conf = config['default']
|
||||
|
||||
if 'downgrade_blacklist' in default_conf:
|
||||
@@ -141,15 +142,15 @@ class Ctx:
|
||||
if os.path.exists(extra_model_paths_yaml):
|
||||
utils.extra_config.load_extra_path_config(extra_model_paths_yaml)
|
||||
|
||||
core.update_user_directory(user_directory)
|
||||
context.update_user_directory(user_directory)
|
||||
|
||||
if os.path.exists(core.manager_pip_overrides_path):
|
||||
with open(core.manager_pip_overrides_path, 'r', encoding="UTF-8", errors="ignore") as json_file:
|
||||
if os.path.exists(context.manager_pip_overrides_path):
|
||||
with open(context.manager_pip_overrides_path, 'r', encoding="UTF-8", errors="ignore") as json_file:
|
||||
cm_global.pip_overrides = json.load(json_file)
|
||||
cm_global.pip_overrides = {'numpy': 'numpy<2'}
|
||||
|
||||
if os.path.exists(core.manager_pip_blacklist_path):
|
||||
with open(core.manager_pip_blacklist_path, 'r', encoding="UTF-8", errors="ignore") as f:
|
||||
if os.path.exists(context.manager_pip_blacklist_path):
|
||||
with open(context.manager_pip_blacklist_path, 'r', encoding="UTF-8", errors="ignore") as f:
|
||||
for x in f.readlines():
|
||||
y = x.strip()
|
||||
if y != '':
|
||||
@@ -162,15 +163,15 @@ class Ctx:
|
||||
|
||||
@staticmethod
|
||||
def get_startup_scripts_path():
|
||||
return os.path.join(core.manager_startup_script_path, "install-scripts.txt")
|
||||
return os.path.join(context.manager_startup_script_path, "install-scripts.txt")
|
||||
|
||||
@staticmethod
|
||||
def get_restore_snapshot_path():
|
||||
return os.path.join(core.manager_startup_script_path, "restore-snapshot.json")
|
||||
return os.path.join(context.manager_startup_script_path, "restore-snapshot.json")
|
||||
|
||||
@staticmethod
|
||||
def get_snapshot_path():
|
||||
return core.manager_snapshot_path
|
||||
return context.manager_snapshot_path
|
||||
|
||||
@staticmethod
|
||||
def get_custom_nodes_paths():
|
||||
@@ -646,7 +647,7 @@ def install(
|
||||
cmd_ctx.set_channel_mode(channel, mode)
|
||||
cmd_ctx.set_no_deps(no_deps)
|
||||
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), comfy_path, core.manager_files_path)
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), comfy_path, context.manager_files_path)
|
||||
for_each_nodes(nodes, act=install_node)
|
||||
pip_fixer.fix_broken()
|
||||
|
||||
@@ -684,7 +685,7 @@ def reinstall(
|
||||
cmd_ctx.set_channel_mode(channel, mode)
|
||||
cmd_ctx.set_no_deps(no_deps)
|
||||
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), comfy_path, core.manager_files_path)
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), comfy_path, context.manager_files_path)
|
||||
for_each_nodes(nodes, act=reinstall_node)
|
||||
pip_fixer.fix_broken()
|
||||
|
||||
@@ -738,7 +739,7 @@ def update(
|
||||
if 'all' in nodes:
|
||||
asyncio.run(auto_save_snapshot())
|
||||
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), comfy_path, core.manager_files_path)
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), comfy_path, context.manager_files_path)
|
||||
|
||||
for x in nodes:
|
||||
if x.lower() in ['comfyui', 'comfy', 'all']:
|
||||
@@ -839,7 +840,7 @@ def fix(
|
||||
if 'all' in nodes:
|
||||
asyncio.run(auto_save_snapshot())
|
||||
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), comfy_path, core.manager_files_path)
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), comfy_path, context.manager_files_path)
|
||||
for_each_nodes(nodes, fix_node, allow_all=True)
|
||||
pip_fixer.fix_broken()
|
||||
|
||||
@@ -1116,7 +1117,7 @@ def restore_snapshot(
|
||||
print(f"[bold red]ERROR: `{snapshot_path}` is not exists.[/bold red]")
|
||||
exit(1)
|
||||
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), comfy_path, core.manager_files_path)
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), comfy_path, context.manager_files_path)
|
||||
try:
|
||||
asyncio.run(core.restore_snapshot(snapshot_path, extras))
|
||||
except Exception:
|
||||
@@ -1148,7 +1149,7 @@ def restore_dependencies(
|
||||
total = len(node_paths)
|
||||
i = 1
|
||||
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), comfy_path, core.manager_files_path)
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), comfy_path, context.manager_files_path)
|
||||
for x in node_paths:
|
||||
print("----------------------------------------------------------------------------------------------------")
|
||||
print(f"Restoring [{i}/{total}]: {x}")
|
||||
@@ -1167,7 +1168,7 @@ def post_install(
|
||||
):
|
||||
path = os.path.expanduser(path)
|
||||
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), comfy_path, core.manager_files_path)
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), comfy_path, context.manager_files_path)
|
||||
unified_manager.execute_install_script('', path, instant_execution=True)
|
||||
pip_fixer.fix_broken()
|
||||
|
||||
@@ -1211,7 +1212,7 @@ def install_deps(
|
||||
print(f"[bold red]Invalid json file: {deps}[/bold red]")
|
||||
exit(1)
|
||||
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), comfy_path, core.manager_files_path)
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), comfy_path, context.manager_files_path)
|
||||
for k in json_obj['custom_nodes'].keys():
|
||||
state = core.simple_check_custom_node(k)
|
||||
if state == 'installed':
|
||||
|
||||
0
comfyui_manager/common/__init__.py
Normal file
0
comfyui_manager/common/__init__.py
Normal file
@@ -6,7 +6,7 @@ import time
|
||||
from dataclasses import dataclass
|
||||
from typing import List
|
||||
|
||||
from . import manager_core
|
||||
from . import context
|
||||
from . import manager_util
|
||||
|
||||
import requests
|
||||
@@ -48,9 +48,9 @@ async def _get_cnr_data(cache_mode=True, dont_wait=True):
|
||||
# Get ComfyUI version tag
|
||||
if is_desktop:
|
||||
# extract version from pyproject.toml instead of git tag
|
||||
comfyui_ver = manager_core.get_current_comfyui_ver() or 'unknown'
|
||||
comfyui_ver = context.get_current_comfyui_ver() or 'unknown'
|
||||
else:
|
||||
comfyui_ver = manager_core.get_comfyui_tag() or 'unknown'
|
||||
comfyui_ver = context.get_comfyui_tag() or 'unknown'
|
||||
|
||||
if is_desktop:
|
||||
if is_windows:
|
||||
109
comfyui_manager/common/context.py
Normal file
109
comfyui_manager/common/context.py
Normal file
@@ -0,0 +1,109 @@
|
||||
import sys
|
||||
import os
|
||||
import logging
|
||||
from . import manager_util
|
||||
import toml
|
||||
import git
|
||||
|
||||
|
||||
# read env vars
|
||||
comfy_path: str = os.environ.get('COMFYUI_PATH')
|
||||
comfy_base_path = os.environ.get('COMFYUI_FOLDERS_BASE_PATH')
|
||||
|
||||
if comfy_path is None:
|
||||
try:
|
||||
comfy_path = os.path.abspath(os.path.dirname(sys.modules['__main__'].__file__))
|
||||
os.environ['COMFYUI_PATH'] = comfy_path
|
||||
except:
|
||||
logging.error("[ComfyUI-Manager] environment variable 'COMFYUI_PATH' is not specified.")
|
||||
exit(-1)
|
||||
|
||||
if comfy_base_path is None:
|
||||
comfy_base_path = comfy_path
|
||||
|
||||
channel_list_template_path = os.path.join(manager_util.comfyui_manager_path, 'channels.list.template')
|
||||
git_script_path = os.path.join(manager_util.comfyui_manager_path, "git_helper.py")
|
||||
|
||||
manager_files_path = None
|
||||
manager_config_path = None
|
||||
manager_channel_list_path = None
|
||||
manager_startup_script_path:str = None
|
||||
manager_snapshot_path = None
|
||||
manager_pip_overrides_path = None
|
||||
manager_pip_blacklist_path = None
|
||||
manager_components_path = None
|
||||
manager_batch_history_path = None
|
||||
|
||||
def update_user_directory(user_dir):
|
||||
global manager_files_path
|
||||
global manager_config_path
|
||||
global manager_channel_list_path
|
||||
global manager_startup_script_path
|
||||
global manager_snapshot_path
|
||||
global manager_pip_overrides_path
|
||||
global manager_pip_blacklist_path
|
||||
global manager_components_path
|
||||
global manager_batch_history_path
|
||||
|
||||
manager_files_path = os.path.abspath(os.path.join(user_dir, 'default', 'ComfyUI-Manager'))
|
||||
if not os.path.exists(manager_files_path):
|
||||
os.makedirs(manager_files_path)
|
||||
|
||||
manager_snapshot_path = os.path.join(manager_files_path, "snapshots")
|
||||
if not os.path.exists(manager_snapshot_path):
|
||||
os.makedirs(manager_snapshot_path)
|
||||
|
||||
manager_startup_script_path = os.path.join(manager_files_path, "startup-scripts")
|
||||
if not os.path.exists(manager_startup_script_path):
|
||||
os.makedirs(manager_startup_script_path)
|
||||
|
||||
manager_config_path = os.path.join(manager_files_path, 'config.ini')
|
||||
manager_channel_list_path = os.path.join(manager_files_path, 'channels.list')
|
||||
manager_pip_overrides_path = os.path.join(manager_files_path, "pip_overrides.json")
|
||||
manager_pip_blacklist_path = os.path.join(manager_files_path, "pip_blacklist.list")
|
||||
manager_components_path = os.path.join(manager_files_path, "components")
|
||||
manager_util.cache_dir = os.path.join(manager_files_path, "cache")
|
||||
manager_batch_history_path = os.path.join(manager_files_path, "batch_history")
|
||||
|
||||
if not os.path.exists(manager_util.cache_dir):
|
||||
os.makedirs(manager_util.cache_dir)
|
||||
|
||||
if not os.path.exists(manager_batch_history_path):
|
||||
os.makedirs(manager_batch_history_path)
|
||||
|
||||
try:
|
||||
import folder_paths
|
||||
update_user_directory(folder_paths.get_user_directory())
|
||||
|
||||
except Exception:
|
||||
# fallback:
|
||||
# This case is only possible when running with cm-cli, and in practice, this case is not actually used.
|
||||
update_user_directory(os.path.abspath(manager_util.comfyui_manager_path))
|
||||
|
||||
|
||||
def get_current_comfyui_ver():
|
||||
"""
|
||||
Extract version from pyproject.toml
|
||||
"""
|
||||
toml_path = os.path.join(comfy_path, 'pyproject.toml')
|
||||
if not os.path.exists(toml_path):
|
||||
return None
|
||||
else:
|
||||
try:
|
||||
with open(toml_path, "r", encoding="utf-8") as f:
|
||||
data = toml.load(f)
|
||||
|
||||
project = data.get('project', {})
|
||||
return project.get('version')
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def get_comfyui_tag():
|
||||
try:
|
||||
with git.Repo(comfy_path) as repo:
|
||||
return repo.git.describe('--tags')
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
0
comfyui_manager/glob/__init__.py
Normal file
0
comfyui_manager/glob/__init__.py
Normal file
@@ -23,7 +23,6 @@ import yaml
|
||||
import zipfile
|
||||
import traceback
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
import toml
|
||||
|
||||
orig_print = print
|
||||
|
||||
@@ -32,13 +31,15 @@ from packaging import version
|
||||
|
||||
import uuid
|
||||
|
||||
from . import cm_global
|
||||
from . import cnr_utils
|
||||
from . import manager_util
|
||||
from . import git_utils
|
||||
from . import manager_downloader
|
||||
from .node_package import InstalledNodePackage
|
||||
from .enums import NetworkMode, SecurityLevel, DBMode
|
||||
from ..common import cm_global
|
||||
from ..common import cnr_utils
|
||||
from ..common import manager_util
|
||||
from ..common import git_utils
|
||||
from ..common import manager_downloader
|
||||
from ..common.node_package import InstalledNodePackage
|
||||
from ..common.enums import NetworkMode, SecurityLevel, DBMode
|
||||
from ..common import context
|
||||
|
||||
|
||||
version_code = [4, 0]
|
||||
version_str = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
|
||||
@@ -77,32 +78,6 @@ def get_custom_nodes_paths():
|
||||
return [custom_nodes_path]
|
||||
|
||||
|
||||
def get_comfyui_tag():
|
||||
try:
|
||||
repo = git.Repo(comfy_path)
|
||||
return repo.git.describe('--tags')
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def get_current_comfyui_ver():
|
||||
"""
|
||||
Extract version from pyproject.toml
|
||||
"""
|
||||
toml_path = os.path.join(comfy_path, 'pyproject.toml')
|
||||
if not os.path.exists(toml_path):
|
||||
return None
|
||||
else:
|
||||
try:
|
||||
with open(toml_path, "r", encoding="utf-8") as f:
|
||||
data = toml.load(f)
|
||||
|
||||
project = data.get('project', {})
|
||||
return project.get('version')
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def get_script_env():
|
||||
new_env = os.environ.copy()
|
||||
git_exe = get_config().get('git_exe')
|
||||
@@ -110,10 +85,10 @@ def get_script_env():
|
||||
new_env['GIT_EXE_PATH'] = git_exe
|
||||
|
||||
if 'COMFYUI_PATH' not in new_env:
|
||||
new_env['COMFYUI_PATH'] = comfy_path
|
||||
new_env['COMFYUI_PATH'] = context.comfy_path
|
||||
|
||||
if 'COMFYUI_FOLDERS_BASE_PATH' not in new_env:
|
||||
new_env['COMFYUI_FOLDERS_BASE_PATH'] = comfy_path
|
||||
new_env['COMFYUI_FOLDERS_BASE_PATH'] = context.comfy_path
|
||||
|
||||
return new_env
|
||||
|
||||
@@ -137,10 +112,10 @@ def check_invalid_nodes():
|
||||
import folder_paths
|
||||
except:
|
||||
try:
|
||||
sys.path.append(comfy_path)
|
||||
sys.path.append(context.comfy_path)
|
||||
import folder_paths
|
||||
except:
|
||||
raise Exception(f"Invalid COMFYUI_FOLDERS_BASE_PATH: {comfy_path}")
|
||||
raise Exception(f"Invalid COMFYUI_FOLDERS_BASE_PATH: {context.comfy_path}")
|
||||
|
||||
def check(root):
|
||||
global invalid_nodes
|
||||
@@ -175,76 +150,6 @@ def check_invalid_nodes():
|
||||
print("\n---------------------------------------------------------------------------\n")
|
||||
|
||||
|
||||
# read env vars
|
||||
comfy_path: str = os.environ.get('COMFYUI_PATH')
|
||||
comfy_base_path = os.environ.get('COMFYUI_FOLDERS_BASE_PATH')
|
||||
|
||||
if comfy_path is None:
|
||||
try:
|
||||
comfy_path = os.path.abspath(os.path.dirname(sys.modules['__main__'].__file__))
|
||||
os.environ['COMFYUI_PATH'] = comfy_path
|
||||
except:
|
||||
logging.error("[ComfyUI-Manager] environment variable 'COMFYUI_PATH' is not specified.")
|
||||
exit(-1)
|
||||
|
||||
if comfy_base_path is None:
|
||||
comfy_base_path = comfy_path
|
||||
|
||||
|
||||
channel_list_template_path = os.path.join(manager_util.comfyui_manager_path, 'channels.list.template')
|
||||
git_script_path = os.path.join(manager_util.comfyui_manager_path, "git_helper.py")
|
||||
|
||||
manager_files_path = None
|
||||
manager_config_path = None
|
||||
manager_channel_list_path = None
|
||||
manager_startup_script_path:str = None
|
||||
manager_snapshot_path = None
|
||||
manager_pip_overrides_path = None
|
||||
manager_pip_blacklist_path = None
|
||||
manager_components_path = None
|
||||
|
||||
def update_user_directory(user_dir):
|
||||
global manager_files_path
|
||||
global manager_config_path
|
||||
global manager_channel_list_path
|
||||
global manager_startup_script_path
|
||||
global manager_snapshot_path
|
||||
global manager_pip_overrides_path
|
||||
global manager_pip_blacklist_path
|
||||
global manager_components_path
|
||||
|
||||
manager_files_path = os.path.abspath(os.path.join(user_dir, 'default', 'ComfyUI-Manager'))
|
||||
if not os.path.exists(manager_files_path):
|
||||
os.makedirs(manager_files_path)
|
||||
|
||||
manager_snapshot_path = os.path.join(manager_files_path, "snapshots")
|
||||
if not os.path.exists(manager_snapshot_path):
|
||||
os.makedirs(manager_snapshot_path)
|
||||
|
||||
manager_startup_script_path = os.path.join(manager_files_path, "startup-scripts")
|
||||
if not os.path.exists(manager_startup_script_path):
|
||||
os.makedirs(manager_startup_script_path)
|
||||
|
||||
manager_config_path = os.path.join(manager_files_path, 'config.ini')
|
||||
manager_channel_list_path = os.path.join(manager_files_path, 'channels.list')
|
||||
manager_pip_overrides_path = os.path.join(manager_files_path, "pip_overrides.json")
|
||||
manager_pip_blacklist_path = os.path.join(manager_files_path, "pip_blacklist.list")
|
||||
manager_components_path = os.path.join(manager_files_path, "components")
|
||||
manager_util.cache_dir = os.path.join(manager_files_path, "cache")
|
||||
|
||||
if not os.path.exists(manager_util.cache_dir):
|
||||
os.makedirs(manager_util.cache_dir)
|
||||
|
||||
try:
|
||||
import folder_paths
|
||||
update_user_directory(folder_paths.get_user_directory())
|
||||
|
||||
except Exception:
|
||||
# fallback:
|
||||
# This case is only possible when running with cm-cli, and in practice, this case is not actually used.
|
||||
update_user_directory(os.path.abspath(manager_util.comfyui_manager_path))
|
||||
|
||||
|
||||
cached_config = None
|
||||
js_path = None
|
||||
|
||||
@@ -729,6 +634,8 @@ class UnifiedManager:
|
||||
return latest
|
||||
|
||||
async def reload(self, cache_mode, dont_wait=True, update_cnr_map=True):
|
||||
import folder_paths
|
||||
|
||||
self.custom_node_map_cache = {}
|
||||
self.cnr_inactive_nodes = {} # node_id -> node_version -> fullpath
|
||||
self.nightly_inactive_nodes = {} # node_id -> fullpath
|
||||
@@ -862,7 +769,7 @@ class UnifiedManager:
|
||||
else:
|
||||
if os.path.exists(requirements_path) and not no_deps:
|
||||
print("Install: pip packages")
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), comfy_path, manager_files_path)
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), context.comfy_path, context.manager_files_path)
|
||||
lines = manager_util.robust_readlines(requirements_path)
|
||||
for line in lines:
|
||||
package_name = remap_pip_package(line.strip())
|
||||
@@ -883,7 +790,7 @@ class UnifiedManager:
|
||||
return res
|
||||
|
||||
def reserve_cnr_switch(self, target, zip_url, from_path, to_path, no_deps):
|
||||
script_path = os.path.join(manager_startup_script_path, "install-scripts.txt")
|
||||
script_path = os.path.join(context.manager_startup_script_path, "install-scripts.txt")
|
||||
with open(script_path, "a") as file:
|
||||
obj = [target, "#LAZY-CNR-SWITCH-SCRIPT", zip_url, from_path, to_path, no_deps, get_default_custom_nodes_path(), sys.executable]
|
||||
file.write(f"{obj}\n")
|
||||
@@ -1289,7 +1196,7 @@ class UnifiedManager:
|
||||
print(f"Download: git clone '{clone_url}'")
|
||||
|
||||
if not instant_execution and platform.system() == 'Windows':
|
||||
res = manager_funcs.run_script([sys.executable, git_script_path, "--clone", get_default_custom_nodes_path(), clone_url, repo_path], cwd=get_default_custom_nodes_path())
|
||||
res = manager_funcs.run_script([sys.executable, context.git_script_path, "--clone", get_default_custom_nodes_path(), clone_url, repo_path], cwd=get_default_custom_nodes_path())
|
||||
if res != 0:
|
||||
return result.fail(f"Failed to clone repo: {clone_url}")
|
||||
else:
|
||||
@@ -1320,67 +1227,66 @@ class UnifiedManager:
|
||||
return result.fail(f'Path not found: {repo_path}')
|
||||
|
||||
# version check
|
||||
repo = git.Repo(repo_path)
|
||||
with git.Repo(repo_path) as repo:
|
||||
if repo.head.is_detached:
|
||||
if not switch_to_default_branch(repo):
|
||||
return result.fail(f"Failed to switch to default branch: {repo_path}")
|
||||
|
||||
if repo.head.is_detached:
|
||||
if not switch_to_default_branch(repo):
|
||||
return result.fail(f"Failed to switch to default branch: {repo_path}")
|
||||
current_branch = repo.active_branch
|
||||
branch_name = current_branch.name
|
||||
|
||||
current_branch = repo.active_branch
|
||||
branch_name = current_branch.name
|
||||
|
||||
if current_branch.tracking_branch() is None:
|
||||
print(f"[ComfyUI-Manager] There is no tracking branch ({current_branch})")
|
||||
remote_name = get_remote_name(repo)
|
||||
else:
|
||||
remote_name = current_branch.tracking_branch().remote_name
|
||||
|
||||
if remote_name is None:
|
||||
return result.fail(f"Failed to get remote when installing: {repo_path}")
|
||||
|
||||
remote = repo.remote(name=remote_name)
|
||||
|
||||
try:
|
||||
remote.fetch()
|
||||
except Exception as e:
|
||||
if 'detected dubious' in str(e):
|
||||
print(f"[ComfyUI-Manager] Try fixing 'dubious repository' error on '{repo_path}' repository")
|
||||
safedir_path = repo_path.replace('\\', '/')
|
||||
subprocess.run(['git', 'config', '--global', '--add', 'safe.directory', safedir_path])
|
||||
try:
|
||||
remote.fetch()
|
||||
except Exception:
|
||||
print("\n[ComfyUI-Manager] Failed to fixing repository setup. Please execute this command on cmd: \n"
|
||||
"-----------------------------------------------------------------------------------------\n"
|
||||
f'git config --global --add safe.directory "{safedir_path}"\n'
|
||||
"-----------------------------------------------------------------------------------------\n")
|
||||
|
||||
commit_hash = repo.head.commit.hexsha
|
||||
if f'{remote_name}/{branch_name}' in repo.refs:
|
||||
remote_commit_hash = repo.refs[f'{remote_name}/{branch_name}'].object.hexsha
|
||||
else:
|
||||
return result.fail(f"Not updatable branch: {branch_name}")
|
||||
|
||||
if commit_hash != remote_commit_hash:
|
||||
git_pull(repo_path)
|
||||
|
||||
if len(repo.remotes) > 0:
|
||||
url = repo.remotes[0].url
|
||||
if current_branch.tracking_branch() is None:
|
||||
print(f"[ComfyUI-Manager] There is no tracking branch ({current_branch})")
|
||||
remote_name = get_remote_name(repo)
|
||||
else:
|
||||
url = "unknown repo"
|
||||
remote_name = current_branch.tracking_branch().remote_name
|
||||
|
||||
def postinstall():
|
||||
return self.execute_install_script(url, repo_path, instant_execution=instant_execution, no_deps=no_deps)
|
||||
if remote_name is None:
|
||||
return result.fail(f"Failed to get remote when installing: {repo_path}")
|
||||
|
||||
if return_postinstall:
|
||||
return result.with_postinstall(postinstall)
|
||||
remote = repo.remote(name=remote_name)
|
||||
|
||||
try:
|
||||
remote.fetch()
|
||||
except Exception as e:
|
||||
if 'detected dubious' in str(e):
|
||||
print(f"[ComfyUI-Manager] Try fixing 'dubious repository' error on '{repo_path}' repository")
|
||||
safedir_path = repo_path.replace('\\', '/')
|
||||
subprocess.run(['git', 'config', '--global', '--add', 'safe.directory', safedir_path])
|
||||
try:
|
||||
remote.fetch()
|
||||
except Exception:
|
||||
print("\n[ComfyUI-Manager] Failed to fixing repository setup. Please execute this command on cmd: \n"
|
||||
"-----------------------------------------------------------------------------------------\n"
|
||||
f'git config --global --add safe.directory "{safedir_path}"\n'
|
||||
"-----------------------------------------------------------------------------------------\n")
|
||||
|
||||
commit_hash = repo.head.commit.hexsha
|
||||
if f'{remote_name}/{branch_name}' in repo.refs:
|
||||
remote_commit_hash = repo.refs[f'{remote_name}/{branch_name}'].object.hexsha
|
||||
else:
|
||||
if not postinstall():
|
||||
return result.fail(f"Failed to execute install script: {url}")
|
||||
return result.fail(f"Not updatable branch: {branch_name}")
|
||||
|
||||
return result
|
||||
else:
|
||||
return ManagedResult('skip').with_msg('Up to date')
|
||||
if commit_hash != remote_commit_hash:
|
||||
git_pull(repo_path)
|
||||
|
||||
if len(repo.remotes) > 0:
|
||||
url = repo.remotes[0].url
|
||||
else:
|
||||
url = "unknown repo"
|
||||
|
||||
def postinstall():
|
||||
return self.execute_install_script(url, repo_path, instant_execution=instant_execution, no_deps=no_deps)
|
||||
|
||||
if return_postinstall:
|
||||
return result.with_postinstall(postinstall)
|
||||
else:
|
||||
if not postinstall():
|
||||
return result.fail(f"Failed to execute install script: {url}")
|
||||
|
||||
return result
|
||||
else:
|
||||
return ManagedResult('skip').with_msg('Up to date')
|
||||
|
||||
def unified_update(self, node_id, version_spec=None, instant_execution=False, no_deps=False, return_postinstall=False):
|
||||
orig_print(f"\x1b[2K\rUpdating: {node_id}", end='')
|
||||
@@ -1571,10 +1477,10 @@ def get_channel_dict():
|
||||
if channel_dict is None:
|
||||
channel_dict = {}
|
||||
|
||||
if not os.path.exists(manager_channel_list_path):
|
||||
shutil.copy(channel_list_template_path, manager_channel_list_path)
|
||||
if not os.path.exists(context.manager_channel_list_path):
|
||||
shutil.copy(context.channel_list_template_path, context.manager_channel_list_path)
|
||||
|
||||
with open(manager_channel_list_path, 'r') as file:
|
||||
with open(context.manager_channel_list_path, 'r') as file:
|
||||
channels = file.read()
|
||||
for x in channels.split('\n'):
|
||||
channel_info = x.split("::")
|
||||
@@ -1638,18 +1544,18 @@ def write_config():
|
||||
'db_mode': get_config()['db_mode'],
|
||||
}
|
||||
|
||||
directory = os.path.dirname(manager_config_path)
|
||||
directory = os.path.dirname(context.manager_config_path)
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
|
||||
with open(manager_config_path, 'w') as configfile:
|
||||
with open(context.manager_config_path, 'w') as configfile:
|
||||
config.write(configfile)
|
||||
|
||||
|
||||
def read_config():
|
||||
try:
|
||||
config = configparser.ConfigParser(strict=False)
|
||||
config.read(manager_config_path)
|
||||
config.read(context.manager_config_path)
|
||||
default_conf = config['default']
|
||||
manager_util.use_uv = default_conf['use_uv'].lower() == 'true' if 'use_uv' in default_conf else False
|
||||
|
||||
@@ -1769,10 +1675,10 @@ def switch_to_default_branch(repo):
|
||||
|
||||
|
||||
def reserve_script(repo_path, install_cmds):
|
||||
if not os.path.exists(manager_startup_script_path):
|
||||
os.makedirs(manager_startup_script_path)
|
||||
if not os.path.exists(context.manager_startup_script_path):
|
||||
os.makedirs(context.manager_startup_script_path)
|
||||
|
||||
script_path = os.path.join(manager_startup_script_path, "install-scripts.txt")
|
||||
script_path = os.path.join(context.manager_startup_script_path, "install-scripts.txt")
|
||||
with open(script_path, "a") as file:
|
||||
obj = [repo_path] + install_cmds
|
||||
file.write(f"{obj}\n")
|
||||
@@ -1827,11 +1733,11 @@ def try_install_script(url, repo_path, install_cmd, instant_execution=False):
|
||||
# use subprocess to avoid file system lock by git (Windows)
|
||||
def __win_check_git_update(path, do_fetch=False, do_update=False):
|
||||
if do_fetch:
|
||||
command = [sys.executable, git_script_path, "--fetch", path]
|
||||
command = [sys.executable, context.git_script_path, "--fetch", path]
|
||||
elif do_update:
|
||||
command = [sys.executable, git_script_path, "--pull", path]
|
||||
command = [sys.executable, context.git_script_path, "--pull", path]
|
||||
else:
|
||||
command = [sys.executable, git_script_path, "--check", path]
|
||||
command = [sys.executable, context.git_script_path, "--check", path]
|
||||
|
||||
new_env = get_script_env()
|
||||
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=get_default_custom_nodes_path(), env=new_env)
|
||||
@@ -1885,7 +1791,7 @@ def __win_check_git_update(path, do_fetch=False, do_update=False):
|
||||
|
||||
|
||||
def __win_check_git_pull(path):
|
||||
command = [sys.executable, git_script_path, "--pull", path]
|
||||
command = [sys.executable, context.git_script_path, "--pull", path]
|
||||
process = subprocess.Popen(command, env=get_script_env(), cwd=get_default_custom_nodes_path())
|
||||
process.wait()
|
||||
|
||||
@@ -1901,7 +1807,7 @@ def execute_install_script(url, repo_path, lazy_mode=False, instant_execution=Fa
|
||||
else:
|
||||
if os.path.exists(requirements_path) and not no_deps:
|
||||
print("Install: pip packages")
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), comfy_path, manager_files_path)
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), context.comfy_path, context.manager_files_path)
|
||||
with open(requirements_path, "r") as requirements_file:
|
||||
for line in requirements_file:
|
||||
#handle comments
|
||||
@@ -2127,7 +2033,7 @@ async def gitclone_install(url, instant_execution=False, msg_prefix='', no_deps=
|
||||
clone_url = git_utils.get_url_for_clone(url)
|
||||
|
||||
if not instant_execution and platform.system() == 'Windows':
|
||||
res = manager_funcs.run_script([sys.executable, git_script_path, "--clone", get_default_custom_nodes_path(), clone_url, repo_path], cwd=get_default_custom_nodes_path())
|
||||
res = manager_funcs.run_script([sys.executable, context.git_script_path, "--clone", get_default_custom_nodes_path(), clone_url, repo_path], cwd=get_default_custom_nodes_path())
|
||||
if res != 0:
|
||||
return result.fail(f"Failed to clone '{clone_url}' into '{repo_path}'")
|
||||
else:
|
||||
@@ -2285,7 +2191,7 @@ def gitclone_uninstall(files):
|
||||
url = url[:-1]
|
||||
try:
|
||||
for custom_nodes_dir in get_custom_nodes_paths():
|
||||
dir_name = os.path.splitext(os.path.basename(url))[0].replace(".git", "")
|
||||
dir_name:str = os.path.splitext(os.path.basename(url))[0].replace(".git", "")
|
||||
dir_path = os.path.join(custom_nodes_dir, dir_name)
|
||||
|
||||
# safety check
|
||||
@@ -2333,7 +2239,7 @@ def gitclone_set_active(files, is_disable):
|
||||
url = url[:-1]
|
||||
try:
|
||||
for custom_nodes_dir in get_custom_nodes_paths():
|
||||
dir_name = os.path.splitext(os.path.basename(url))[0].replace(".git", "")
|
||||
dir_name:str = os.path.splitext(os.path.basename(url))[0].replace(".git", "")
|
||||
dir_path = os.path.join(custom_nodes_dir, dir_name)
|
||||
|
||||
# safety check
|
||||
@@ -2606,7 +2512,7 @@ async def get_current_snapshot(custom_nodes_only = False):
|
||||
await unified_manager.get_custom_nodes('default', 'cache')
|
||||
|
||||
# Get ComfyUI hash
|
||||
repo_path = comfy_path
|
||||
repo_path = context.comfy_path
|
||||
|
||||
comfyui_commit_hash = None
|
||||
if not custom_nodes_only:
|
||||
@@ -2648,22 +2554,8 @@ async def get_current_snapshot(custom_nodes_only = False):
|
||||
|
||||
cnr_custom_nodes[info['id']] = info['ver']
|
||||
else:
|
||||
repo = git.Repo(fullpath)
|
||||
|
||||
if repo.head.is_detached:
|
||||
remote_name = get_remote_name(repo)
|
||||
else:
|
||||
current_branch = repo.active_branch
|
||||
|
||||
if current_branch.tracking_branch() is None:
|
||||
remote_name = get_remote_name(repo)
|
||||
else:
|
||||
remote_name = current_branch.tracking_branch().remote_name
|
||||
|
||||
commit_hash = repo.head.commit.hexsha
|
||||
|
||||
url = repo.remotes[remote_name].url
|
||||
|
||||
commit_hash = git_utils.get_commit_hash(fullpath)
|
||||
url = git_utils.git_url(fullpath)
|
||||
git_custom_nodes[url] = dict(hash=commit_hash, disabled=is_disabled)
|
||||
except:
|
||||
print(f"Failed to extract snapshots for the custom node '{path}'.")
|
||||
@@ -2696,7 +2588,7 @@ async def save_snapshot_with_postfix(postfix, path=None, custom_nodes_only = Fal
|
||||
date_time_format = now.strftime("%Y-%m-%d_%H-%M-%S")
|
||||
file_name = f"{date_time_format}_{postfix}"
|
||||
|
||||
path = os.path.join(manager_snapshot_path, f"{file_name}.json")
|
||||
path = os.path.join(context.manager_snapshot_path, f"{file_name}.json")
|
||||
else:
|
||||
file_name = path.replace('\\', '/').split('/')[-1]
|
||||
file_name = file_name.split('.')[-2]
|
||||
@@ -3278,7 +3170,7 @@ async def restore_snapshot(snapshot_path, git_helper_extras=None):
|
||||
|
||||
def get_comfyui_versions(repo=None):
|
||||
if repo is None:
|
||||
repo = git.Repo(comfy_path)
|
||||
repo = git.Repo(context.comfy_path)
|
||||
|
||||
try:
|
||||
remote = get_remote_name(repo)
|
||||
@@ -3312,7 +3204,7 @@ def get_comfyui_versions(repo=None):
|
||||
|
||||
|
||||
def switch_comfyui(tag):
|
||||
repo = git.Repo(comfy_path)
|
||||
repo = git.Repo(context.comfy_path)
|
||||
|
||||
if tag == 'nightly':
|
||||
repo.git.checkout('master')
|
||||
|
||||
@@ -16,12 +16,13 @@ from datetime import datetime
|
||||
from server import PromptServer
|
||||
import logging
|
||||
import asyncio
|
||||
import queue
|
||||
from collections import deque
|
||||
|
||||
from . import manager_core as core
|
||||
from . import manager_util
|
||||
from . import cm_global
|
||||
from . import manager_downloader
|
||||
from ..common import manager_util
|
||||
from ..common import cm_global
|
||||
from ..common import manager_downloader
|
||||
from ..common import context
|
||||
|
||||
|
||||
logging.info(f"### Loading: ComfyUI-Manager ({core.version_str})")
|
||||
@@ -160,10 +161,10 @@ class ManagerFuncsInComfyUI(core.ManagerFuncs):
|
||||
|
||||
core.manager_funcs = ManagerFuncsInComfyUI()
|
||||
|
||||
from .manager_downloader import download_url, download_url_with_agent
|
||||
from comfyui_manager.common.manager_downloader import download_url, download_url_with_agent
|
||||
|
||||
core.comfy_path = os.path.dirname(folder_paths.__file__)
|
||||
core.js_path = os.path.join(core.comfy_path, "web", "extensions")
|
||||
context.comfy_path = os.path.dirname(folder_paths.__file__)
|
||||
core.js_path = os.path.join(context.comfy_path, "web", "extensions")
|
||||
|
||||
local_db_model = os.path.join(manager_util.comfyui_manager_path, "model-list.json")
|
||||
local_db_alter = os.path.join(manager_util.comfyui_manager_path, "alter-list.json")
|
||||
@@ -214,7 +215,7 @@ def print_comfyui_version():
|
||||
is_detached = repo.head.is_detached
|
||||
current_branch = repo.active_branch.name
|
||||
|
||||
comfyui_tag = core.get_comfyui_tag()
|
||||
comfyui_tag = context.get_comfyui_tag()
|
||||
|
||||
try:
|
||||
if not os.environ.get('__COMFYUI_DESKTOP_VERSION__') and core.comfy_ui_commit_datetime.date() < core.comfy_ui_required_commit_datetime.date():
|
||||
@@ -394,16 +395,73 @@ def nickname_filter(json_obj):
|
||||
return json_obj
|
||||
|
||||
|
||||
task_queue = queue.Queue()
|
||||
nodepack_result = {}
|
||||
model_result = {}
|
||||
class TaskBatch:
|
||||
def __init__(self, batch_json, tasks, failed):
|
||||
self.nodepack_result = {}
|
||||
self.model_result = {}
|
||||
self.batch_id = batch_json.get('batch_id') if batch_json is not None else None
|
||||
self.batch_json = batch_json
|
||||
self.tasks = tasks
|
||||
self.current_index = 0
|
||||
self.stats = {}
|
||||
self.failed = failed if failed is not None else set()
|
||||
self.is_aborted = False
|
||||
|
||||
def is_done(self):
|
||||
return len(self.tasks) <= self.current_index
|
||||
|
||||
def get_next(self):
|
||||
if self.is_done():
|
||||
return None
|
||||
|
||||
item = self.tasks[self.current_index]
|
||||
self.current_index += 1
|
||||
return item
|
||||
|
||||
def done_count(self):
|
||||
return len(self.nodepack_result) + len(self.model_result)
|
||||
|
||||
def total_count(self):
|
||||
return len(self.tasks)
|
||||
|
||||
def abort(self):
|
||||
self.is_aborted = True
|
||||
|
||||
def finalize(self):
|
||||
if self.batch_id is not None:
|
||||
batch_path = os.path.join(context.manager_batch_history_path, self.batch_id+".json")
|
||||
json_obj = {
|
||||
"batch": self.batch_json,
|
||||
"nodepack_result": self.nodepack_result,
|
||||
"model_result": self.model_result,
|
||||
"failed": list(self.failed)
|
||||
}
|
||||
with open(batch_path, "w") as json_file:
|
||||
json.dump(json_obj, json_file, indent=4)
|
||||
|
||||
|
||||
temp_queue_batch = []
|
||||
task_batch_queue = deque()
|
||||
tasks_in_progress = set()
|
||||
task_worker_lock = threading.Lock()
|
||||
aborted_batch = None
|
||||
|
||||
|
||||
def finalize_temp_queue_batch(batch_json=None, failed=None):
|
||||
"""
|
||||
make temp_queue_batch as a batch snapshot and add to batch_queue
|
||||
"""
|
||||
|
||||
global temp_queue_batch
|
||||
|
||||
if len(temp_queue_batch):
|
||||
batch = TaskBatch(batch_json, temp_queue_batch, failed)
|
||||
task_batch_queue.append(batch)
|
||||
temp_queue_batch = []
|
||||
|
||||
|
||||
async def task_worker():
|
||||
global task_queue
|
||||
global nodepack_result
|
||||
global model_result
|
||||
global tasks_in_progress
|
||||
|
||||
async def do_install(item) -> str:
|
||||
@@ -416,8 +474,7 @@ async def task_worker():
|
||||
return f"Cannot resolve install target: '{node_spec_str}'"
|
||||
|
||||
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)
|
||||
# discard post install if skip_post_install mode
|
||||
res = await core.unified_manager.install_by_id(node_name, version_spec, channel, mode, return_postinstall=skip_post_install) # discard post install if skip_post_install mode
|
||||
|
||||
if res.action not in ['skip', 'enable', 'install-git', 'install-cnr', 'switch-cnr']:
|
||||
logging.error(f"[ComfyUI-Manager] Installation failed:\n{res.msg}")
|
||||
@@ -432,6 +489,11 @@ async def task_worker():
|
||||
traceback.print_exc()
|
||||
return f"Installation failed:\n{node_spec_str}"
|
||||
|
||||
async def do_enable(item) -> str:
|
||||
ui_id, cnr_id = item
|
||||
core.unified_manager.unified_enable(cnr_id)
|
||||
return 'success'
|
||||
|
||||
async def do_update(item):
|
||||
ui_id, node_name, node_ver = item
|
||||
|
||||
@@ -590,31 +652,45 @@ async def task_worker():
|
||||
|
||||
return f"Model installation error: {model_url}"
|
||||
|
||||
stats = {}
|
||||
|
||||
while True:
|
||||
done_count = len(nodepack_result) + len(model_result)
|
||||
total_count = done_count + task_queue.qsize()
|
||||
with task_worker_lock:
|
||||
if len(task_batch_queue) > 0:
|
||||
cur_batch = task_batch_queue[0]
|
||||
else:
|
||||
logging.info("\n[ComfyUI-Manager] All tasks are completed.")
|
||||
logging.info("\nAfter restarting ComfyUI, please refresh the browser.")
|
||||
|
||||
if task_queue.empty():
|
||||
logging.info(f"\n[ComfyUI-Manager] Queued works are completed.\n{stats}")
|
||||
res = {'status': 'all-done'}
|
||||
|
||||
logging.info("\nAfter restarting ComfyUI, please refresh the browser.")
|
||||
PromptServer.instance.send_sync("cm-queue-status",
|
||||
{'status': 'done',
|
||||
'nodepack_result': nodepack_result, 'model_result': model_result,
|
||||
'total_count': total_count, 'done_count': done_count})
|
||||
nodepack_result = {}
|
||||
task_queue = queue.Queue()
|
||||
return # terminate worker thread
|
||||
PromptServer.instance.send_sync("cm-queue-status", res)
|
||||
|
||||
return
|
||||
|
||||
if cur_batch.is_done():
|
||||
logging.info(f"\n[ComfyUI-Manager] A tasks batch(batch_id={cur_batch.batch_id}) is completed.\nstat={cur_batch.stats}")
|
||||
|
||||
res = {'status': 'batch-done',
|
||||
'nodepack_result': cur_batch.nodepack_result,
|
||||
'model_result': cur_batch.model_result,
|
||||
'total_count': cur_batch.total_count(),
|
||||
'done_count': cur_batch.done_count(),
|
||||
'batch_id': cur_batch.batch_id,
|
||||
'remaining_batch_count': len(task_batch_queue) }
|
||||
|
||||
PromptServer.instance.send_sync("cm-queue-status", res)
|
||||
cur_batch.finalize()
|
||||
task_batch_queue.popleft()
|
||||
continue
|
||||
|
||||
with task_worker_lock:
|
||||
kind, item = task_queue.get()
|
||||
kind, item = cur_batch.get_next()
|
||||
tasks_in_progress.add((kind, item[0]))
|
||||
|
||||
try:
|
||||
if kind == 'install':
|
||||
msg = await do_install(item)
|
||||
elif kind == 'enable':
|
||||
msg = await do_enable(item)
|
||||
elif kind == 'install-model':
|
||||
msg = await do_install_model(item)
|
||||
elif kind == 'update':
|
||||
@@ -638,28 +714,128 @@ async def task_worker():
|
||||
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"
|
||||
elif kind == 'update-main':
|
||||
nodepack_result[ui_id] = msg
|
||||
ui_target = "main"
|
||||
elif kind == 'update-comfyui':
|
||||
nodepack_result['comfyui'] = msg
|
||||
ui_target = "main"
|
||||
elif kind == 'update':
|
||||
nodepack_result[ui_id] = msg['msg']
|
||||
ui_target = "nodepack_manager"
|
||||
else:
|
||||
nodepack_result[ui_id] = msg
|
||||
ui_target = "nodepack_manager"
|
||||
ui_id = item[0]
|
||||
if kind == 'install-model':
|
||||
cur_batch.model_result[ui_id] = msg
|
||||
ui_target = "model_manager"
|
||||
elif kind == 'update-main':
|
||||
cur_batch.nodepack_result[ui_id] = msg
|
||||
ui_target = "main"
|
||||
elif kind == 'update-comfyui':
|
||||
cur_batch.nodepack_result['comfyui'] = msg
|
||||
ui_target = "main"
|
||||
elif kind == 'update':
|
||||
cur_batch.nodepack_result[ui_id] = msg['msg']
|
||||
ui_target = "nodepack_manager"
|
||||
else:
|
||||
cur_batch.nodepack_result[ui_id] = msg
|
||||
ui_target = "nodepack_manager"
|
||||
|
||||
stats[kind] = stats.get(kind, 0) + 1
|
||||
cur_batch.stats[kind] = cur_batch.stats.get(kind, 0) + 1
|
||||
|
||||
PromptServer.instance.send_sync("cm-queue-status",
|
||||
{'status': 'in_progress', 'target': item[0], 'ui_target': ui_target,
|
||||
'total_count': total_count, 'done_count': done_count})
|
||||
{'status': 'in_progress',
|
||||
'target': item[0],
|
||||
'batch_id': cur_batch.batch_id,
|
||||
'ui_target': ui_target,
|
||||
'total_count': cur_batch.total_count(),
|
||||
'done_count': cur_batch.done_count()})
|
||||
|
||||
|
||||
@routes.post("/v2/manager/queue/batch")
|
||||
async def queue_batch(request):
|
||||
json_data = await request.json()
|
||||
|
||||
failed = set()
|
||||
|
||||
for k, v in json_data.items():
|
||||
if k == 'update_all':
|
||||
await _update_all({'mode': v})
|
||||
|
||||
elif k == 'reinstall':
|
||||
for x in v:
|
||||
res = await _uninstall_custom_node(x)
|
||||
if res.status != 200:
|
||||
failed.add(x[0])
|
||||
else:
|
||||
res = await _install_custom_node(x)
|
||||
if res.status != 200:
|
||||
failed.add(x[0])
|
||||
|
||||
elif k == 'install':
|
||||
for x in v:
|
||||
res = await _install_custom_node(x)
|
||||
if res.status != 200:
|
||||
failed.add(x[0])
|
||||
|
||||
elif k == 'uninstall':
|
||||
for x in v:
|
||||
res = await _uninstall_custom_node(x)
|
||||
if res.status != 200:
|
||||
failed.add(x[0])
|
||||
|
||||
elif k == 'update':
|
||||
for x in v:
|
||||
res = await _update_custom_node(x)
|
||||
if res.status != 200:
|
||||
failed.add(x[0])
|
||||
|
||||
elif k == 'update_comfyui':
|
||||
await update_comfyui(None)
|
||||
|
||||
elif k == 'disable':
|
||||
for x in v:
|
||||
await _disable_node(x)
|
||||
|
||||
elif k == 'install_model':
|
||||
for x in v:
|
||||
res = await _install_model(x)
|
||||
if res.status != 200:
|
||||
failed.add(x[0])
|
||||
|
||||
elif k == 'fix':
|
||||
for x in v:
|
||||
res = await _fix_custom_node(x)
|
||||
if res.status != 200:
|
||||
failed.add(x[0])
|
||||
|
||||
with task_worker_lock:
|
||||
finalize_temp_queue_batch(json_data, failed)
|
||||
_queue_start()
|
||||
|
||||
return web.json_response({"failed": list(failed)}, content_type='application/json')
|
||||
|
||||
|
||||
@routes.get("/v2/manager/queue/history_list")
|
||||
async def get_history_list(request):
|
||||
history_path = context.manager_batch_history_path
|
||||
|
||||
try:
|
||||
files = [os.path.join(history_path, f) for f in os.listdir(history_path) if os.path.isfile(os.path.join(history_path, f))]
|
||||
files.sort(key=lambda x: os.path.getmtime(x), reverse=True)
|
||||
history_ids = [os.path.basename(f)[:-5] for f in files]
|
||||
|
||||
return web.json_response({"ids": list(history_ids)}, content_type='application/json')
|
||||
except Exception as e:
|
||||
logging.error(f"[ComfyUI-Manager] /v2/manager/queue/history_list - {e}")
|
||||
return web.Response(status=400)
|
||||
|
||||
|
||||
@routes.get("/v2/manager/queue/history")
|
||||
async def get_history(request):
|
||||
try:
|
||||
json_name = request.rel_url.query["id"]+'.json'
|
||||
batch_path = os.path.join(context.manager_batch_history_path, json_name)
|
||||
|
||||
with open(batch_path, 'r', encoding='utf-8') as file:
|
||||
json_str = file.read()
|
||||
json_obj = json.loads(json_str)
|
||||
return web.json_response(json_obj, content_type='application/json')
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"[ComfyUI-Manager] /v2/manager/queue/history - {e}")
|
||||
|
||||
return web.Response(status=400)
|
||||
|
||||
|
||||
@routes.get("/v2/customnode/getmappings")
|
||||
@@ -727,6 +903,11 @@ async def fetch_updates(request):
|
||||
|
||||
@routes.get("/v2/manager/queue/update_all")
|
||||
async def update_all(request):
|
||||
json_data = dict(request.rel_url.query)
|
||||
return await _update_all(json_data)
|
||||
|
||||
|
||||
async def _update_all(json_data):
|
||||
if not is_allowed_security_level('middle'):
|
||||
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
||||
return web.Response(status=403)
|
||||
@@ -738,13 +919,13 @@ async def update_all(request):
|
||||
|
||||
await core.save_snapshot_with_postfix('autosave')
|
||||
|
||||
if request.rel_url.query["mode"] == "local":
|
||||
if json_data["mode"] == "local":
|
||||
channel = 'local'
|
||||
else:
|
||||
channel = core.get_config()['channel_url']
|
||||
|
||||
await core.unified_manager.reload(request.rel_url.query["mode"])
|
||||
await core.unified_manager.get_custom_nodes(channel, request.rel_url.query["mode"])
|
||||
await core.unified_manager.reload(json_data["mode"])
|
||||
await core.unified_manager.get_custom_nodes(channel, json_data["mode"])
|
||||
|
||||
for k, v in core.unified_manager.active_nodes.items():
|
||||
if k == 'comfyui-manager':
|
||||
@@ -753,7 +934,7 @@ async def update_all(request):
|
||||
continue
|
||||
|
||||
update_item = k, k, v[0]
|
||||
task_queue.put(("update-main", update_item))
|
||||
temp_queue_batch.append(("update-main", update_item))
|
||||
|
||||
for k, v in core.unified_manager.unknown_active_nodes.items():
|
||||
if k == 'comfyui-manager':
|
||||
@@ -762,7 +943,7 @@ async def update_all(request):
|
||||
continue
|
||||
|
||||
update_item = k, k, 'unknown'
|
||||
task_queue.put(("update-main", update_item))
|
||||
temp_queue_batch.append(("update-main", update_item))
|
||||
|
||||
return web.Response(status=200)
|
||||
|
||||
@@ -810,6 +991,13 @@ def populate_markdown(x):
|
||||
if 'title' in x:
|
||||
x['title'] = manager_util.sanitize_tag(x['title'])
|
||||
|
||||
@routes.get("/v2/manager/is_legacy_manager_ui")
|
||||
async def is_legacy_manager_ui(request):
|
||||
return web.json_response(
|
||||
{"is_legacy_manager_ui": args.enable_manager_legacy_ui},
|
||||
content_type="application/json",
|
||||
status=200,
|
||||
)
|
||||
|
||||
# freeze imported version
|
||||
startup_time_installed_node_packs = core.get_installed_node_packs()
|
||||
@@ -953,7 +1141,7 @@ async def fetch_externalmodel_list(request):
|
||||
|
||||
@PromptServer.instance.routes.get("/v2/snapshot/getlist")
|
||||
async def get_snapshot_list(request):
|
||||
items = [f[:-5] for f in os.listdir(core.manager_snapshot_path) if f.endswith('.json')]
|
||||
items = [f[:-5] for f in os.listdir(context.manager_snapshot_path) if f.endswith('.json')]
|
||||
items.sort(reverse=True)
|
||||
return web.json_response({'items': items}, content_type='application/json')
|
||||
|
||||
@@ -967,7 +1155,7 @@ async def remove_snapshot(request):
|
||||
try:
|
||||
target = request.rel_url.query["target"]
|
||||
|
||||
path = os.path.join(core.manager_snapshot_path, f"{target}.json")
|
||||
path = os.path.join(context.manager_snapshot_path, f"{target}.json")
|
||||
if os.path.exists(path):
|
||||
os.remove(path)
|
||||
|
||||
@@ -985,12 +1173,12 @@ async def restore_snapshot(request):
|
||||
try:
|
||||
target = request.rel_url.query["target"]
|
||||
|
||||
path = os.path.join(core.manager_snapshot_path, f"{target}.json")
|
||||
path = os.path.join(context.manager_snapshot_path, f"{target}.json")
|
||||
if os.path.exists(path):
|
||||
if not os.path.exists(core.manager_startup_script_path):
|
||||
os.makedirs(core.manager_startup_script_path)
|
||||
if not os.path.exists(context.manager_startup_script_path):
|
||||
os.makedirs(context.manager_startup_script_path)
|
||||
|
||||
target_path = os.path.join(core.manager_startup_script_path, "restore-snapshot.json")
|
||||
target_path = os.path.join(context.manager_startup_script_path, "restore-snapshot.json")
|
||||
shutil.copy(path, target_path)
|
||||
|
||||
logging.info(f"Snapshot restore scheduled: `{target}`")
|
||||
@@ -1099,8 +1287,27 @@ async def reinstall_custom_node(request):
|
||||
|
||||
@routes.get("/v2/manager/queue/reset")
|
||||
async def reset_queue(request):
|
||||
global task_queue
|
||||
task_queue = queue.Queue()
|
||||
global task_batch_queue
|
||||
global temp_queue_batch
|
||||
|
||||
with task_worker_lock:
|
||||
temp_queue_batch = []
|
||||
task_batch_queue = deque()
|
||||
|
||||
return web.Response(status=200)
|
||||
|
||||
|
||||
@routes.get("/v2/manager/queue/abort_current")
|
||||
async def abort_queue(request):
|
||||
global task_batch_queue
|
||||
global temp_queue_batch
|
||||
|
||||
with task_worker_lock:
|
||||
temp_queue_batch = []
|
||||
if len(task_batch_queue) > 0:
|
||||
task_batch_queue[0].abort()
|
||||
task_batch_queue.popleft()
|
||||
|
||||
return web.Response(status=200)
|
||||
|
||||
|
||||
@@ -1109,24 +1316,37 @@ async def queue_count(request):
|
||||
global task_queue
|
||||
|
||||
with task_worker_lock:
|
||||
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()
|
||||
if len(task_batch_queue) > 0:
|
||||
cur_batch = task_batch_queue[0]
|
||||
done_count = cur_batch.done_count()
|
||||
total_count = cur_batch.total_count()
|
||||
in_progress_count = len(tasks_in_progress)
|
||||
is_processing = task_worker_thread is not None and task_worker_thread.is_alive()
|
||||
else:
|
||||
done_count = 0
|
||||
total_count = 0
|
||||
in_progress_count = 0
|
||||
is_processing = False
|
||||
|
||||
return web.json_response({
|
||||
'total_count': total_count, 'done_count': done_count, 'in_progress_count': in_progress_count,
|
||||
'total_count': total_count,
|
||||
'done_count': done_count,
|
||||
'in_progress_count': in_progress_count,
|
||||
'is_processing': is_processing})
|
||||
|
||||
|
||||
@routes.post("/v2/manager/queue/install")
|
||||
async def install_custom_node(request):
|
||||
json_data = await request.json()
|
||||
print(f"install={json_data}")
|
||||
return await _install_custom_node(json_data)
|
||||
|
||||
|
||||
async def _install_custom_node(json_data):
|
||||
if not is_allowed_security_level('middle'):
|
||||
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
||||
return web.Response(status=403, text="A security error has occurred. Please check the terminal logs")
|
||||
|
||||
json_data = await request.json()
|
||||
|
||||
# non-nightly cnr is safe
|
||||
risky_level = None
|
||||
cnr_id = json_data.get('id')
|
||||
@@ -1138,8 +1358,10 @@ async def install_custom_node(request):
|
||||
if json_data['version'] != 'unknown' and selected_version != 'unknown':
|
||||
if skip_post_install:
|
||||
if cnr_id in core.unified_manager.nightly_inactive_nodes or cnr_id in core.unified_manager.cnr_inactive_nodes:
|
||||
core.unified_manager.unified_enable(cnr_id)
|
||||
enable_item = json_data.get('ui_id'), cnr_id
|
||||
temp_queue_batch.append(("enable", enable_item))
|
||||
return web.Response(status=200)
|
||||
|
||||
elif selected_version is None:
|
||||
selected_version = 'latest'
|
||||
|
||||
@@ -1152,9 +1374,11 @@ async def install_custom_node(request):
|
||||
if git_url is None:
|
||||
logging.error(f"[ComfyUI-Manager] Following node pack doesn't provide `nightly` version: ${git_url}")
|
||||
return web.Response(status=404, text=f"Following node pack doesn't provide `nightly` version: ${git_url}")
|
||||
|
||||
elif json_data['version'] != 'unknown' and selected_version == 'unknown':
|
||||
logging.error(f"[ComfyUI-Manager] Invalid installation request: {json_data}")
|
||||
return web.Response(status=400, text="Invalid installation request")
|
||||
|
||||
else:
|
||||
# unknown
|
||||
unknown_name = os.path.basename(json_data['files'][0])
|
||||
@@ -1173,7 +1397,7 @@ async def install_custom_node(request):
|
||||
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
|
||||
task_queue.put(("install", install_item))
|
||||
temp_queue_batch.append(("install", install_item))
|
||||
|
||||
return web.Response(status=200)
|
||||
|
||||
@@ -1182,16 +1406,16 @@ task_worker_thread:threading.Thread = None
|
||||
|
||||
@routes.get("/v2/manager/queue/start")
|
||||
async def queue_start(request):
|
||||
global nodepack_result
|
||||
global model_result
|
||||
with task_worker_lock:
|
||||
finalize_temp_queue_batch()
|
||||
return _queue_start()
|
||||
|
||||
def _queue_start():
|
||||
global task_worker_thread
|
||||
|
||||
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()
|
||||
|
||||
@@ -1200,12 +1424,15 @@ async def queue_start(request):
|
||||
|
||||
@routes.post("/v2/manager/queue/fix")
|
||||
async def fix_custom_node(request):
|
||||
json_data = await request.json()
|
||||
return await _fix_custom_node(json_data)
|
||||
|
||||
|
||||
async def _fix_custom_node(json_data):
|
||||
if not is_allowed_security_level('middle'):
|
||||
logging.error(SECURITY_MESSAGE_GENERAL)
|
||||
return web.Response(status=403, text="A security error has occurred. Please check the terminal logs")
|
||||
|
||||
json_data = await request.json()
|
||||
|
||||
node_id = json_data.get('id')
|
||||
node_ver = json_data['version']
|
||||
if node_ver != 'unknown':
|
||||
@@ -1215,7 +1442,7 @@ async def fix_custom_node(request):
|
||||
node_name = os.path.basename(json_data['files'][0])
|
||||
|
||||
update_item = json_data.get('ui_id'), node_name, json_data['version']
|
||||
task_queue.put(("fix", update_item))
|
||||
temp_queue_batch.append(("fix", update_item))
|
||||
|
||||
return web.Response(status=200)
|
||||
|
||||
@@ -1254,12 +1481,15 @@ async def install_custom_node_pip(request):
|
||||
|
||||
@routes.post("/v2/manager/queue/uninstall")
|
||||
async def uninstall_custom_node(request):
|
||||
json_data = await request.json()
|
||||
return await _uninstall_custom_node(json_data)
|
||||
|
||||
|
||||
async def _uninstall_custom_node(json_data):
|
||||
if not is_allowed_security_level('middle'):
|
||||
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
||||
return web.Response(status=403, text="A security error has occurred. Please check the terminal logs")
|
||||
|
||||
json_data = await request.json()
|
||||
|
||||
node_id = json_data.get('id')
|
||||
if json_data['version'] != 'unknown':
|
||||
is_unknown = False
|
||||
@@ -1270,19 +1500,22 @@ async def uninstall_custom_node(request):
|
||||
node_name = os.path.basename(json_data['files'][0])
|
||||
|
||||
uninstall_item = json_data.get('ui_id'), node_name, is_unknown
|
||||
task_queue.put(("uninstall", uninstall_item))
|
||||
temp_queue_batch.append(("uninstall", uninstall_item))
|
||||
|
||||
return web.Response(status=200)
|
||||
|
||||
|
||||
@routes.post("/v2/manager/queue/update")
|
||||
async def update_custom_node(request):
|
||||
json_data = await request.json()
|
||||
return await _update_custom_node(json_data)
|
||||
|
||||
|
||||
async def _update_custom_node(json_data):
|
||||
if not is_allowed_security_level('middle'):
|
||||
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
||||
return web.Response(status=403, text="A security error has occurred. Please check the terminal logs")
|
||||
|
||||
json_data = await request.json()
|
||||
|
||||
node_id = json_data.get('id')
|
||||
if json_data['version'] != 'unknown':
|
||||
node_name = node_id
|
||||
@@ -1291,7 +1524,7 @@ async def update_custom_node(request):
|
||||
node_name = os.path.basename(json_data['files'][0])
|
||||
|
||||
update_item = json_data.get('ui_id'), node_name, json_data['version']
|
||||
task_queue.put(("update", update_item))
|
||||
temp_queue_batch.append(("update", update_item))
|
||||
|
||||
return web.Response(status=200)
|
||||
|
||||
@@ -1299,7 +1532,7 @@ async def update_custom_node(request):
|
||||
@routes.get("/v2/manager/queue/update_comfyui")
|
||||
async def update_comfyui(request):
|
||||
is_stable = core.get_config()['update_policy'] != 'nightly-comfyui'
|
||||
task_queue.put(("update-comfyui", ('comfyui', is_stable)))
|
||||
temp_queue_batch.append(("update-comfyui", ('comfyui', is_stable)))
|
||||
return web.Response(status=200)
|
||||
|
||||
|
||||
@@ -1330,7 +1563,11 @@ async def comfyui_switch_version(request):
|
||||
@routes.post("/v2/manager/queue/disable")
|
||||
async def disable_node(request):
|
||||
json_data = await request.json()
|
||||
await _disable_node(json_data)
|
||||
return web.Response(status=200)
|
||||
|
||||
|
||||
async def _disable_node(json_data):
|
||||
node_id = json_data.get('id')
|
||||
if json_data['version'] != 'unknown':
|
||||
is_unknown = False
|
||||
@@ -1341,9 +1578,7 @@ async def disable_node(request):
|
||||
node_name = os.path.basename(json_data['files'][0])
|
||||
|
||||
update_item = json_data.get('ui_id'), node_name, is_unknown
|
||||
task_queue.put(("disable", update_item))
|
||||
|
||||
return web.Response(status=200)
|
||||
temp_queue_batch.append(("disable", update_item))
|
||||
|
||||
|
||||
async def check_whitelist_for_model(item):
|
||||
@@ -1365,7 +1600,10 @@ async def check_whitelist_for_model(item):
|
||||
@routes.post("/v2/manager/queue/install_model")
|
||||
async def install_model(request):
|
||||
json_data = await request.json()
|
||||
return await _install_model(json_data)
|
||||
|
||||
|
||||
async def _install_model(json_data):
|
||||
if not is_allowed_security_level('middle'):
|
||||
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
||||
return web.Response(status=403, text="A security error has occurred. Please check the terminal logs")
|
||||
@@ -1389,7 +1627,7 @@ async def install_model(request):
|
||||
return web.Response(status=403, text="A security error has occurred. Please check the terminal logs")
|
||||
|
||||
install_item = json_data.get('ui_id'), json_data
|
||||
task_queue.put(("install-model", install_item))
|
||||
temp_queue_batch.append(("install-model", install_item))
|
||||
|
||||
return web.Response(status=200)
|
||||
|
||||
@@ -1496,7 +1734,7 @@ async def get_notice(request):
|
||||
if version_tag is not None:
|
||||
markdown_content += f"<HR>ComfyUI: {version_tag} [Desktop]"
|
||||
else:
|
||||
version_tag = core.get_comfyui_tag()
|
||||
version_tag = context.get_comfyui_tag()
|
||||
if version_tag is None:
|
||||
markdown_content += f"<HR>ComfyUI: {core.comfy_ui_revision}[{comfy_ui_hash[:6]}]({core.comfy_ui_commit_datetime.date()})"
|
||||
else:
|
||||
@@ -1573,15 +1811,15 @@ async def save_component(request):
|
||||
name = data['name']
|
||||
workflow = data['workflow']
|
||||
|
||||
if not os.path.exists(core.manager_components_path):
|
||||
os.mkdir(core.manager_components_path)
|
||||
if not os.path.exists(context.manager_components_path):
|
||||
os.mkdir(context.manager_components_path)
|
||||
|
||||
if 'packname' in workflow and workflow['packname'] != '':
|
||||
sanitized_name = manager_util.sanitize_filename(workflow['packname']) + '.pack'
|
||||
else:
|
||||
sanitized_name = manager_util.sanitize_filename(name) + '.json'
|
||||
|
||||
filepath = os.path.join(core.manager_components_path, sanitized_name)
|
||||
filepath = os.path.join(context.manager_components_path, sanitized_name)
|
||||
components = {}
|
||||
if os.path.exists(filepath):
|
||||
with open(filepath) as f:
|
||||
@@ -1598,14 +1836,14 @@ async def save_component(request):
|
||||
|
||||
@routes.post("/v2/manager/component/loads")
|
||||
async def load_components(request):
|
||||
if os.path.exists(core.manager_components_path):
|
||||
if os.path.exists(context.manager_components_path):
|
||||
try:
|
||||
json_files = [f for f in os.listdir(core.manager_components_path) if f.endswith('.json')]
|
||||
pack_files = [f for f in os.listdir(core.manager_components_path) if f.endswith('.pack')]
|
||||
json_files = [f for f in os.listdir(context.manager_components_path) if f.endswith('.json')]
|
||||
pack_files = [f for f in os.listdir(context.manager_components_path) if f.endswith('.pack')]
|
||||
|
||||
components = {}
|
||||
for json_file in json_files + pack_files:
|
||||
file_path = os.path.join(core.manager_components_path, json_file)
|
||||
file_path = os.path.join(context.manager_components_path, json_file)
|
||||
with open(file_path, 'r') as file:
|
||||
try:
|
||||
# When there is a conflict between the .pack and the .json, the pack takes precedence and overrides.
|
||||
@@ -1693,7 +1931,7 @@ async def default_cache_update():
|
||||
|
||||
threading.Thread(target=lambda: asyncio.run(default_cache_update())).start()
|
||||
|
||||
if not os.path.exists(core.manager_config_path):
|
||||
if not os.path.exists(context.manager_config_path):
|
||||
core.get_config()
|
||||
core.write_config()
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import mimetypes
|
||||
from ..common import context
|
||||
from . import manager_core as core
|
||||
|
||||
import os
|
||||
@@ -66,10 +67,10 @@ async def share_option(request):
|
||||
|
||||
|
||||
def get_openart_auth():
|
||||
if not os.path.exists(os.path.join(core.manager_files_path, ".openart_key")):
|
||||
if not os.path.exists(os.path.join(context.manager_files_path, ".openart_key")):
|
||||
return None
|
||||
try:
|
||||
with open(os.path.join(core.manager_files_path, ".openart_key"), "r") as f:
|
||||
with open(os.path.join(context.manager_files_path, ".openart_key"), "r") as f:
|
||||
openart_key = f.read().strip()
|
||||
return openart_key if openart_key else None
|
||||
except:
|
||||
@@ -77,10 +78,10 @@ def get_openart_auth():
|
||||
|
||||
|
||||
def get_matrix_auth():
|
||||
if not os.path.exists(os.path.join(core.manager_files_path, "matrix_auth")):
|
||||
if not os.path.exists(os.path.join(context.manager_files_path, "matrix_auth")):
|
||||
return None
|
||||
try:
|
||||
with open(os.path.join(core.manager_files_path, "matrix_auth"), "r") as f:
|
||||
with open(os.path.join(context.manager_files_path, "matrix_auth"), "r") as f:
|
||||
matrix_auth = f.read()
|
||||
homeserver, username, password = matrix_auth.strip().split("\n")
|
||||
if not homeserver or not username or not password:
|
||||
@@ -95,10 +96,10 @@ def get_matrix_auth():
|
||||
|
||||
|
||||
def get_comfyworkflows_auth():
|
||||
if not os.path.exists(os.path.join(core.manager_files_path, "comfyworkflows_sharekey")):
|
||||
if not os.path.exists(os.path.join(context.manager_files_path, "comfyworkflows_sharekey")):
|
||||
return None
|
||||
try:
|
||||
with open(os.path.join(core.manager_files_path, "comfyworkflows_sharekey"), "r") as f:
|
||||
with open(os.path.join(context.manager_files_path, "comfyworkflows_sharekey"), "r") as f:
|
||||
share_key = f.read()
|
||||
if not share_key.strip():
|
||||
return None
|
||||
@@ -108,10 +109,10 @@ def get_comfyworkflows_auth():
|
||||
|
||||
|
||||
def get_youml_settings():
|
||||
if not os.path.exists(os.path.join(core.manager_files_path, ".youml")):
|
||||
if not os.path.exists(os.path.join(context.manager_files_path, ".youml")):
|
||||
return None
|
||||
try:
|
||||
with open(os.path.join(core.manager_files_path, ".youml"), "r") as f:
|
||||
with open(os.path.join(context.manager_files_path, ".youml"), "r") as f:
|
||||
youml_settings = f.read().strip()
|
||||
return youml_settings if youml_settings else None
|
||||
except:
|
||||
@@ -119,7 +120,7 @@ def get_youml_settings():
|
||||
|
||||
|
||||
def set_youml_settings(settings):
|
||||
with open(os.path.join(core.manager_files_path, ".youml"), "w") as f:
|
||||
with open(os.path.join(context.manager_files_path, ".youml"), "w") as f:
|
||||
f.write(settings)
|
||||
|
||||
|
||||
@@ -136,7 +137,7 @@ async def api_get_openart_auth(request):
|
||||
async def api_set_openart_auth(request):
|
||||
json_data = await request.json()
|
||||
openart_key = json_data['openart_key']
|
||||
with open(os.path.join(core.manager_files_path, ".openart_key"), "w") as f:
|
||||
with open(os.path.join(context.manager_files_path, ".openart_key"), "w") as f:
|
||||
f.write(openart_key)
|
||||
return web.Response(status=200)
|
||||
|
||||
@@ -179,14 +180,14 @@ async def api_get_comfyworkflows_auth(request):
|
||||
@PromptServer.instance.routes.post("/v2/manager/set_esheep_workflow_and_images")
|
||||
async def set_esheep_workflow_and_images(request):
|
||||
json_data = await request.json()
|
||||
with open(os.path.join(core.manager_files_path, "esheep_share_message.json"), "w", encoding='utf-8') as file:
|
||||
with open(os.path.join(context.manager_files_path, "esheep_share_message.json"), "w", encoding='utf-8') as file:
|
||||
json.dump(json_data, file, indent=4)
|
||||
return web.Response(status=200)
|
||||
|
||||
|
||||
@PromptServer.instance.routes.get("/v2/manager/get_esheep_workflow_and_images")
|
||||
async def get_esheep_workflow_and_images(request):
|
||||
with open(os.path.join(core.manager_files_path, "esheep_share_message.json"), 'r', encoding='utf-8') as file:
|
||||
with open(os.path.join(context.manager_files_path, "esheep_share_message.json"), 'r', encoding='utf-8') as file:
|
||||
data = json.load(file)
|
||||
return web.Response(status=200, text=json.dumps(data))
|
||||
|
||||
@@ -195,12 +196,12 @@ def set_matrix_auth(json_data):
|
||||
homeserver = json_data['homeserver']
|
||||
username = json_data['username']
|
||||
password = json_data['password']
|
||||
with open(os.path.join(core.manager_files_path, "matrix_auth"), "w") as f:
|
||||
with open(os.path.join(context.manager_files_path, "matrix_auth"), "w") as f:
|
||||
f.write("\n".join([homeserver, username, password]))
|
||||
|
||||
|
||||
def set_comfyworkflows_auth(comfyworkflows_sharekey):
|
||||
with open(os.path.join(core.manager_files_path, "comfyworkflows_sharekey"), "w") as f:
|
||||
with open(os.path.join(context.manager_files_path, "comfyworkflows_sharekey"), "w") as f:
|
||||
f.write(comfyworkflows_sharekey)
|
||||
|
||||
|
||||
|
||||
@@ -14,9 +14,9 @@ import { OpenArtShareDialog } from "./comfyui-share-openart.js";
|
||||
import {
|
||||
free_models, install_pip, install_via_git_url, manager_instance,
|
||||
rebootAPI, setManagerInstance, show_message, customAlert, customPrompt,
|
||||
infoToast, showTerminal, setNeedRestart
|
||||
infoToast, showTerminal, setNeedRestart, generateUUID
|
||||
} from "./common.js";
|
||||
import { ComponentBuilderDialog, getPureName, load_components, set_component_policy } from "./components-manager.js";
|
||||
import { ComponentBuilderDialog, load_components, set_component_policy } from "./components-manager.js";
|
||||
import { CustomNodesManager } from "./custom-nodes-manager.js";
|
||||
import { ModelManager } from "./model-manager.js";
|
||||
import { SnapshotManager } from "./snapshot.js";
|
||||
@@ -223,7 +223,7 @@ function isBeforeFrontendVersion(compareVersion) {
|
||||
}
|
||||
|
||||
const is_legacy_front = () => isBeforeFrontendVersion('1.2.49');
|
||||
const isNewManagerUI = () => isBeforeFrontendVersion('1.16.4');
|
||||
const isNotNewManagerUI = () => isBeforeFrontendVersion('1.16.4');
|
||||
|
||||
document.head.appendChild(docStyle);
|
||||
|
||||
@@ -234,7 +234,7 @@ var restart_stop_button = null;
|
||||
var update_policy_combo = null;
|
||||
|
||||
let share_option = 'all';
|
||||
var is_updating = false;
|
||||
var batch_id = null;
|
||||
|
||||
|
||||
// copied style from https://github.com/pythongosssss/ComfyUI-Custom-Scripts
|
||||
@@ -476,14 +476,19 @@ async function updateComfyUI() {
|
||||
let prev_text = update_comfyui_button.innerText;
|
||||
update_comfyui_button.innerText = "Updating ComfyUI...";
|
||||
|
||||
set_inprogress_mode();
|
||||
|
||||
const response = await api.fetchApi('/v2/manager/queue/update_comfyui');
|
||||
|
||||
// set_inprogress_mode();
|
||||
showTerminal();
|
||||
|
||||
is_updating = true;
|
||||
await api.fetchApi('/v2/manager/queue/start');
|
||||
batch_id = generateUUID();
|
||||
|
||||
let batch = {};
|
||||
batch['batch_id'] = batch_id;
|
||||
batch['update_comfyui'] = true;
|
||||
|
||||
const res = await api.fetchApi(`/v2/manager/queue/batch`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(batch)
|
||||
});
|
||||
}
|
||||
|
||||
function showVersionSelectorDialog(versions, current, onSelect) {
|
||||
@@ -658,18 +663,17 @@ async function onQueueStatus(event) {
|
||||
const isElectron = 'electronAPI' in window;
|
||||
|
||||
if(event.detail.status == 'in_progress') {
|
||||
set_inprogress_mode();
|
||||
// set_inprogress_mode();
|
||||
update_all_button.innerText = `in progress.. (${event.detail.done_count}/${event.detail.total_count})`;
|
||||
}
|
||||
else if(event.detail.status == 'done') {
|
||||
else if(event.detail.status == 'all-done') {
|
||||
reset_action_buttons();
|
||||
|
||||
if(!is_updating) {
|
||||
}
|
||||
else if(event.detail.status == 'batch-done') {
|
||||
if(batch_id != event.detail.batch_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
is_updating = false;
|
||||
|
||||
let success_list = [];
|
||||
let failed_list = [];
|
||||
let comfyui_state = null;
|
||||
@@ -769,41 +773,28 @@ api.addEventListener("cm-queue-status", onQueueStatus);
|
||||
async function updateAll(update_comfyui) {
|
||||
update_all_button.innerText = "Updating...";
|
||||
|
||||
set_inprogress_mode();
|
||||
// set_inprogress_mode();
|
||||
|
||||
var mode = manager_instance.datasrc_combo.value;
|
||||
|
||||
showTerminal();
|
||||
|
||||
batch_id = generateUUID();
|
||||
|
||||
let batch = {};
|
||||
if(update_comfyui) {
|
||||
update_all_button.innerText = "Updating ComfyUI...";
|
||||
await api.fetchApi('/v2/manager/queue/update_comfyui');
|
||||
batch['update_comfyui'] = true;
|
||||
}
|
||||
|
||||
const response = await api.fetchApi(`/v2/manager/queue/update_all?mode=${mode}`);
|
||||
batch['update_all'] = mode;
|
||||
|
||||
if (response.status == 401) {
|
||||
customAlert('Another task is already in progress. Please stop the ongoing task first.');
|
||||
}
|
||||
else if(response.status == 200) {
|
||||
is_updating = true;
|
||||
await api.fetchApi('/v2/manager/queue/start');
|
||||
}
|
||||
const res = await api.fetchApi(`/v2/manager/queue/batch`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(batch)
|
||||
});
|
||||
}
|
||||
|
||||
function newDOMTokenList(initialTokens) {
|
||||
const tmp = document.createElement(`div`);
|
||||
|
||||
const classList = tmp.classList;
|
||||
if (initialTokens) {
|
||||
initialTokens.forEach(token => {
|
||||
classList.add(token);
|
||||
});
|
||||
}
|
||||
|
||||
return classList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the node is a potential output node (img, gif or video output)
|
||||
*/
|
||||
@@ -1527,7 +1518,7 @@ app.registerExtension({
|
||||
}).element
|
||||
);
|
||||
|
||||
const shouldShowLegacyMenuItems = !isNewManagerUI();
|
||||
const shouldShowLegacyMenuItems = isNotNewManagerUI();
|
||||
if (shouldShowLegacyMenuItems) {
|
||||
app.menu?.settingsGroup.element.before(cmGroup.element);
|
||||
}
|
||||
|
||||
@@ -630,6 +630,14 @@ export function showTooltip(target, text, className = 'cn-tooltip', styleMap = {
|
||||
});
|
||||
}
|
||||
|
||||
export function generateUUID() {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||
const r = Math.random() * 16 | 0;
|
||||
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
|
||||
function initTooltip () {
|
||||
const mouseenterHandler = (e) => {
|
||||
const target = e.target;
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
fetchData, md5, icons, show_message, customConfirm, customAlert, customPrompt,
|
||||
sanitizeHTML, infoToast, showTerminal, setNeedRestart,
|
||||
storeColumnWidth, restoreColumnWidth, getTimeAgo, copyText, loadCss,
|
||||
showPopover, hidePopover
|
||||
showPopover, hidePopover, generateUUID
|
||||
} from "./common.js";
|
||||
|
||||
// https://cenfun.github.io/turbogrid/api.html
|
||||
@@ -1439,13 +1439,6 @@ export class CustomNodesManager {
|
||||
}
|
||||
|
||||
async installNodes(list, btn, title, selected_version) {
|
||||
let stats = await api.fetchApi('/v2/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;
|
||||
}
|
||||
|
||||
const { target, label, mode} = btn;
|
||||
|
||||
if(mode === "uninstall") {
|
||||
@@ -1472,10 +1465,10 @@ export class CustomNodesManager {
|
||||
let needRestart = false;
|
||||
let errorMsg = "";
|
||||
|
||||
await api.fetchApi('/v2/manager/queue/reset');
|
||||
|
||||
let target_items = [];
|
||||
|
||||
let batch = {};
|
||||
|
||||
for (const hash of list) {
|
||||
const item = this.grid.getRowItemBy("hash", hash);
|
||||
target_items.push(item);
|
||||
@@ -1517,23 +1510,11 @@ export class CustomNodesManager {
|
||||
api_mode = 'reinstall';
|
||||
}
|
||||
|
||||
const res = await api.fetchApi(`/v2/manager/queue/${api_mode}`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (res.status != 200) {
|
||||
errorMsg = `'${item.title}': `;
|
||||
|
||||
if(res.status == 403) {
|
||||
errorMsg += `This action is not allowed with this security level configuration.\n`;
|
||||
} else if(res.status == 404) {
|
||||
errorMsg += `With the current security level configuration, only custom nodes from the <B>"default channel"</B> can be installed.\n`;
|
||||
} else {
|
||||
errorMsg += await res.text() + '\n';
|
||||
}
|
||||
|
||||
break;
|
||||
if(batch[api_mode]) {
|
||||
batch[api_mode].push(data);
|
||||
}
|
||||
else {
|
||||
batch[api_mode] = [data];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1550,7 +1531,24 @@ export class CustomNodesManager {
|
||||
}
|
||||
}
|
||||
else {
|
||||
await api.fetchApi('/v2/manager/queue/start');
|
||||
this.batch_id = generateUUID();
|
||||
batch['batch_id'] = this.batch_id;
|
||||
|
||||
const res = await api.fetchApi(`/v2/manager/queue/batch`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(batch)
|
||||
});
|
||||
|
||||
let failed = await res.json();
|
||||
|
||||
if(failed.length > 0) {
|
||||
for(let k in failed) {
|
||||
let hash = failed[k];
|
||||
const item = this.grid.getRowItemBy("hash", hash);
|
||||
errorMsg = `[FAIL] ${item.title}`;
|
||||
}
|
||||
}
|
||||
|
||||
this.showStop();
|
||||
showTerminal();
|
||||
}
|
||||
@@ -1571,7 +1569,7 @@ export class CustomNodesManager {
|
||||
self.grid.updateCell(item, "action");
|
||||
self.grid.setRowSelected(item, false);
|
||||
}
|
||||
else if(event.detail.status == 'done') {
|
||||
else if(event.detail.status == 'batch-done' && event.detail.batch_id == self.batch_id) {
|
||||
self.hideStop();
|
||||
self.onQueueCompleted(event.detail);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { $el } from "../../scripts/ui.js";
|
||||
import {
|
||||
manager_instance, rebootAPI,
|
||||
fetchData, md5, icons, show_message, customAlert, infoToast, showTerminal,
|
||||
storeColumnWidth, restoreColumnWidth, loadCss
|
||||
storeColumnWidth, restoreColumnWidth, loadCss, generateUUID
|
||||
} from "./common.js";
|
||||
import { api } from "../../scripts/api.js";
|
||||
|
||||
@@ -413,24 +413,16 @@ export class ModelManager {
|
||||
}
|
||||
|
||||
async installModels(list, btn) {
|
||||
let stats = await api.fetchApi('/v2/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");
|
||||
this.showError("");
|
||||
|
||||
let needRefresh = false;
|
||||
let errorMsg = "";
|
||||
|
||||
await api.fetchApi('/v2/manager/queue/reset');
|
||||
|
||||
let target_items = [];
|
||||
|
||||
let batch = {};
|
||||
|
||||
for (const item of list) {
|
||||
this.grid.scrollRowIntoView(item);
|
||||
target_items.push(item);
|
||||
@@ -446,21 +438,12 @@ export class ModelManager {
|
||||
const data = item.originalData;
|
||||
data.ui_id = item.hash;
|
||||
|
||||
const res = await api.fetchApi(`/v2/manager/queue/install_model`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (res.status != 200) {
|
||||
errorMsg = `'${item.name}': `;
|
||||
|
||||
if(res.status == 403) {
|
||||
errorMsg += `This action is not allowed with this security level configuration.\n`;
|
||||
} else {
|
||||
errorMsg += await res.text() + '\n';
|
||||
}
|
||||
|
||||
break;
|
||||
if(batch['install_model']) {
|
||||
batch['install_model'].push(data);
|
||||
}
|
||||
else {
|
||||
batch['install_model'] = [data];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -477,7 +460,24 @@ export class ModelManager {
|
||||
}
|
||||
}
|
||||
else {
|
||||
await api.fetchApi('/v2/manager/queue/start');
|
||||
this.batch_id = generateUUID();
|
||||
batch['batch_id'] = this.batch_id;
|
||||
|
||||
const res = await api.fetchApi(`/v2/manager/queue/batch`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(batch)
|
||||
});
|
||||
|
||||
let failed = await res.json();
|
||||
|
||||
if(failed.length > 0) {
|
||||
for(let k in failed) {
|
||||
let hash = failed[k];
|
||||
const item = self.grid.getRowItemBy("hash", hash);
|
||||
errorMsg = `[FAIL] ${item.title}`;
|
||||
}
|
||||
}
|
||||
|
||||
this.showStop();
|
||||
showTerminal();
|
||||
}
|
||||
@@ -497,7 +497,7 @@ export class ModelManager {
|
||||
// self.grid.updateCell(item, "tg-column-select");
|
||||
self.grid.updateRow(item);
|
||||
}
|
||||
else if(event.detail.status == 'done') {
|
||||
else if(event.detail.status == 'batch-done') {
|
||||
self.hideStop();
|
||||
self.onQueueCompleted(event.detail);
|
||||
}
|
||||
|
||||
0
comfyui_manager/legacy/__init__.py
Normal file
0
comfyui_manager/legacy/__init__.py
Normal file
3248
comfyui_manager/legacy/manager_core.py
Normal file
3248
comfyui_manager/legacy/manager_core.py
Normal file
File diff suppressed because it is too large
Load Diff
1946
comfyui_manager/legacy/manager_server.py
Normal file
1946
comfyui_manager/legacy/manager_server.py
Normal file
File diff suppressed because it is too large
Load Diff
386
comfyui_manager/legacy/share_3rdparty.py
Normal file
386
comfyui_manager/legacy/share_3rdparty.py
Normal file
@@ -0,0 +1,386 @@
|
||||
import mimetypes
|
||||
from ..common import context
|
||||
from . import manager_core as core
|
||||
|
||||
import os
|
||||
from aiohttp import web
|
||||
import aiohttp
|
||||
import json
|
||||
import hashlib
|
||||
|
||||
import folder_paths
|
||||
from server import PromptServer
|
||||
|
||||
|
||||
def extract_model_file_names(json_data):
|
||||
"""Extract unique file names from the input JSON data."""
|
||||
file_names = set()
|
||||
model_filename_extensions = {'.safetensors', '.ckpt', '.pt', '.pth', '.bin'}
|
||||
|
||||
# Recursively search for file names in the JSON data
|
||||
def recursive_search(data):
|
||||
if isinstance(data, dict):
|
||||
for value in data.values():
|
||||
recursive_search(value)
|
||||
elif isinstance(data, list):
|
||||
for item in data:
|
||||
recursive_search(item)
|
||||
elif isinstance(data, str) and '.' in data:
|
||||
file_names.add(os.path.basename(data)) # file_names.add(data)
|
||||
|
||||
recursive_search(json_data)
|
||||
return [f for f in list(file_names) if os.path.splitext(f)[1] in model_filename_extensions]
|
||||
|
||||
|
||||
def find_file_paths(base_dir, file_names):
|
||||
"""Find the paths of the files in the base directory."""
|
||||
file_paths = {}
|
||||
|
||||
for root, dirs, files in os.walk(base_dir):
|
||||
# Exclude certain directories
|
||||
dirs[:] = [d for d in dirs if d not in ['.git']]
|
||||
|
||||
for file in files:
|
||||
if file in file_names:
|
||||
file_paths[file] = os.path.join(root, file)
|
||||
return file_paths
|
||||
|
||||
|
||||
def compute_sha256_checksum(filepath):
|
||||
"""Compute the SHA256 checksum of a file, in chunks"""
|
||||
sha256 = hashlib.sha256()
|
||||
with open(filepath, 'rb') as f:
|
||||
for chunk in iter(lambda: f.read(4096), b''):
|
||||
sha256.update(chunk)
|
||||
return sha256.hexdigest()
|
||||
|
||||
|
||||
@PromptServer.instance.routes.get("/v2/manager/share_option")
|
||||
async def share_option(request):
|
||||
if "value" in request.rel_url.query:
|
||||
core.get_config()['share_option'] = request.rel_url.query['value']
|
||||
core.write_config()
|
||||
else:
|
||||
return web.Response(text=core.get_config()['share_option'], status=200)
|
||||
|
||||
return web.Response(status=200)
|
||||
|
||||
|
||||
def get_openart_auth():
|
||||
if not os.path.exists(os.path.join(context.manager_files_path, ".openart_key")):
|
||||
return None
|
||||
try:
|
||||
with open(os.path.join(context.manager_files_path, ".openart_key"), "r") as f:
|
||||
openart_key = f.read().strip()
|
||||
return openart_key if openart_key else None
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def get_matrix_auth():
|
||||
if not os.path.exists(os.path.join(context.manager_files_path, "matrix_auth")):
|
||||
return None
|
||||
try:
|
||||
with open(os.path.join(context.manager_files_path, "matrix_auth"), "r") as f:
|
||||
matrix_auth = f.read()
|
||||
homeserver, username, password = matrix_auth.strip().split("\n")
|
||||
if not homeserver or not username or not password:
|
||||
return None
|
||||
return {
|
||||
"homeserver": homeserver,
|
||||
"username": username,
|
||||
"password": password,
|
||||
}
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def get_comfyworkflows_auth():
|
||||
if not os.path.exists(os.path.join(context.manager_files_path, "comfyworkflows_sharekey")):
|
||||
return None
|
||||
try:
|
||||
with open(os.path.join(context.manager_files_path, "comfyworkflows_sharekey"), "r") as f:
|
||||
share_key = f.read()
|
||||
if not share_key.strip():
|
||||
return None
|
||||
return share_key
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def get_youml_settings():
|
||||
if not os.path.exists(os.path.join(context.manager_files_path, ".youml")):
|
||||
return None
|
||||
try:
|
||||
with open(os.path.join(context.manager_files_path, ".youml"), "r") as f:
|
||||
youml_settings = f.read().strip()
|
||||
return youml_settings if youml_settings else None
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def set_youml_settings(settings):
|
||||
with open(os.path.join(context.manager_files_path, ".youml"), "w") as f:
|
||||
f.write(settings)
|
||||
|
||||
|
||||
@PromptServer.instance.routes.get("/v2/manager/get_openart_auth")
|
||||
async def api_get_openart_auth(request):
|
||||
# print("Getting stored Matrix credentials...")
|
||||
openart_key = get_openart_auth()
|
||||
if not openart_key:
|
||||
return web.Response(status=404)
|
||||
return web.json_response({"openart_key": openart_key})
|
||||
|
||||
|
||||
@PromptServer.instance.routes.post("/v2/manager/set_openart_auth")
|
||||
async def api_set_openart_auth(request):
|
||||
json_data = await request.json()
|
||||
openart_key = json_data['openart_key']
|
||||
with open(os.path.join(context.manager_files_path, ".openart_key"), "w") as f:
|
||||
f.write(openart_key)
|
||||
return web.Response(status=200)
|
||||
|
||||
|
||||
@PromptServer.instance.routes.get("/v2/manager/get_matrix_auth")
|
||||
async def api_get_matrix_auth(request):
|
||||
# print("Getting stored Matrix credentials...")
|
||||
matrix_auth = get_matrix_auth()
|
||||
if not matrix_auth:
|
||||
return web.Response(status=404)
|
||||
return web.json_response(matrix_auth)
|
||||
|
||||
|
||||
@PromptServer.instance.routes.get("/v2/manager/youml/settings")
|
||||
async def api_get_youml_settings(request):
|
||||
youml_settings = get_youml_settings()
|
||||
if not youml_settings:
|
||||
return web.Response(status=404)
|
||||
return web.json_response(json.loads(youml_settings))
|
||||
|
||||
|
||||
@PromptServer.instance.routes.post("/v2/manager/youml/settings")
|
||||
async def api_set_youml_settings(request):
|
||||
json_data = await request.json()
|
||||
set_youml_settings(json.dumps(json_data))
|
||||
return web.Response(status=200)
|
||||
|
||||
|
||||
@PromptServer.instance.routes.get("/v2/manager/get_comfyworkflows_auth")
|
||||
async def api_get_comfyworkflows_auth(request):
|
||||
# Check if the user has provided Matrix credentials in a file called 'matrix_accesstoken'
|
||||
# in the same directory as the ComfyUI base folder
|
||||
# print("Getting stored Comfyworkflows.com auth...")
|
||||
comfyworkflows_auth = get_comfyworkflows_auth()
|
||||
if not comfyworkflows_auth:
|
||||
return web.Response(status=404)
|
||||
return web.json_response({"comfyworkflows_sharekey": comfyworkflows_auth})
|
||||
|
||||
|
||||
@PromptServer.instance.routes.post("/v2/manager/set_esheep_workflow_and_images")
|
||||
async def set_esheep_workflow_and_images(request):
|
||||
json_data = await request.json()
|
||||
with open(os.path.join(context.manager_files_path, "esheep_share_message.json"), "w", encoding='utf-8') as file:
|
||||
json.dump(json_data, file, indent=4)
|
||||
return web.Response(status=200)
|
||||
|
||||
|
||||
@PromptServer.instance.routes.get("/v2/manager/get_esheep_workflow_and_images")
|
||||
async def get_esheep_workflow_and_images(request):
|
||||
with open(os.path.join(context.manager_files_path, "esheep_share_message.json"), 'r', encoding='utf-8') as file:
|
||||
data = json.load(file)
|
||||
return web.Response(status=200, text=json.dumps(data))
|
||||
|
||||
|
||||
def set_matrix_auth(json_data):
|
||||
homeserver = json_data['homeserver']
|
||||
username = json_data['username']
|
||||
password = json_data['password']
|
||||
with open(os.path.join(context.manager_files_path, "matrix_auth"), "w") as f:
|
||||
f.write("\n".join([homeserver, username, password]))
|
||||
|
||||
|
||||
def set_comfyworkflows_auth(comfyworkflows_sharekey):
|
||||
with open(os.path.join(context.manager_files_path, "comfyworkflows_sharekey"), "w") as f:
|
||||
f.write(comfyworkflows_sharekey)
|
||||
|
||||
|
||||
def has_provided_matrix_auth(matrix_auth):
|
||||
return matrix_auth['homeserver'].strip() and matrix_auth['username'].strip() and matrix_auth['password'].strip()
|
||||
|
||||
|
||||
def has_provided_comfyworkflows_auth(comfyworkflows_sharekey):
|
||||
return comfyworkflows_sharekey.strip()
|
||||
|
||||
|
||||
@PromptServer.instance.routes.post("/v2/manager/share")
|
||||
async def share_art(request):
|
||||
# get json data
|
||||
json_data = await request.json()
|
||||
|
||||
matrix_auth = json_data['matrix_auth']
|
||||
comfyworkflows_sharekey = json_data['cw_auth']['cw_sharekey']
|
||||
|
||||
set_matrix_auth(matrix_auth)
|
||||
set_comfyworkflows_auth(comfyworkflows_sharekey)
|
||||
|
||||
share_destinations = json_data['share_destinations']
|
||||
credits = json_data['credits']
|
||||
title = json_data['title']
|
||||
description = json_data['description']
|
||||
is_nsfw = json_data['is_nsfw']
|
||||
prompt = json_data['prompt']
|
||||
potential_outputs = json_data['potential_outputs']
|
||||
selected_output_index = json_data['selected_output_index']
|
||||
|
||||
try:
|
||||
output_to_share = potential_outputs[int(selected_output_index)]
|
||||
except:
|
||||
# for now, pick the first output
|
||||
output_to_share = potential_outputs[0]
|
||||
|
||||
assert output_to_share['type'] in ('image', 'output')
|
||||
output_dir = folder_paths.get_output_directory()
|
||||
|
||||
if output_to_share['type'] == 'image':
|
||||
asset_filename = output_to_share['image']['filename']
|
||||
asset_subfolder = output_to_share['image']['subfolder']
|
||||
|
||||
if output_to_share['image']['type'] == 'temp':
|
||||
output_dir = folder_paths.get_temp_directory()
|
||||
else:
|
||||
asset_filename = output_to_share['output']['filename']
|
||||
asset_subfolder = output_to_share['output']['subfolder']
|
||||
|
||||
if asset_subfolder:
|
||||
asset_filepath = os.path.join(output_dir, asset_subfolder, asset_filename)
|
||||
else:
|
||||
asset_filepath = os.path.join(output_dir, asset_filename)
|
||||
|
||||
# get the mime type of the asset
|
||||
assetFileType = mimetypes.guess_type(asset_filepath)[0]
|
||||
|
||||
share_website_host = "UNKNOWN"
|
||||
if "comfyworkflows" in share_destinations:
|
||||
share_website_host = "https://comfyworkflows.com"
|
||||
share_endpoint = f"{share_website_host}/api"
|
||||
|
||||
# get presigned urls
|
||||
async with aiohttp.ClientSession(trust_env=True, connector=aiohttp.TCPConnector(verify_ssl=False)) as session:
|
||||
async with session.post(
|
||||
f"{share_endpoint}/get_presigned_urls",
|
||||
json={
|
||||
"assetFileName": asset_filename,
|
||||
"assetFileType": assetFileType,
|
||||
"workflowJsonFileName": 'workflow.json',
|
||||
"workflowJsonFileType": 'application/json',
|
||||
},
|
||||
) as resp:
|
||||
assert resp.status == 200
|
||||
presigned_urls_json = await resp.json()
|
||||
assetFilePresignedUrl = presigned_urls_json["assetFilePresignedUrl"]
|
||||
assetFileKey = presigned_urls_json["assetFileKey"]
|
||||
workflowJsonFilePresignedUrl = presigned_urls_json["workflowJsonFilePresignedUrl"]
|
||||
workflowJsonFileKey = presigned_urls_json["workflowJsonFileKey"]
|
||||
|
||||
# upload asset
|
||||
async with aiohttp.ClientSession(trust_env=True, connector=aiohttp.TCPConnector(verify_ssl=False)) as session:
|
||||
async with session.put(assetFilePresignedUrl, data=open(asset_filepath, "rb")) as resp:
|
||||
assert resp.status == 200
|
||||
|
||||
# upload workflow json
|
||||
async with aiohttp.ClientSession(trust_env=True, connector=aiohttp.TCPConnector(verify_ssl=False)) as session:
|
||||
async with session.put(workflowJsonFilePresignedUrl, data=json.dumps(prompt['workflow']).encode('utf-8')) as resp:
|
||||
assert resp.status == 200
|
||||
|
||||
model_filenames = extract_model_file_names(prompt['workflow'])
|
||||
model_file_paths = find_file_paths(folder_paths.base_path, model_filenames)
|
||||
|
||||
models_info = {}
|
||||
for filename, filepath in model_file_paths.items():
|
||||
models_info[filename] = {
|
||||
"filename": filename,
|
||||
"sha256_checksum": compute_sha256_checksum(filepath),
|
||||
"relative_path": os.path.relpath(filepath, folder_paths.base_path),
|
||||
}
|
||||
|
||||
# make a POST request to /api/upload_workflow with form data key values
|
||||
async with aiohttp.ClientSession(trust_env=True, connector=aiohttp.TCPConnector(verify_ssl=False)) as session:
|
||||
form = aiohttp.FormData()
|
||||
if comfyworkflows_sharekey:
|
||||
form.add_field("shareKey", comfyworkflows_sharekey)
|
||||
form.add_field("source", "comfyui_manager")
|
||||
form.add_field("assetFileKey", assetFileKey)
|
||||
form.add_field("assetFileType", assetFileType)
|
||||
form.add_field("workflowJsonFileKey", workflowJsonFileKey)
|
||||
form.add_field("sharedWorkflowWorkflowJsonString", json.dumps(prompt['workflow']))
|
||||
form.add_field("sharedWorkflowPromptJsonString", json.dumps(prompt['output']))
|
||||
form.add_field("shareWorkflowCredits", credits)
|
||||
form.add_field("shareWorkflowTitle", title)
|
||||
form.add_field("shareWorkflowDescription", description)
|
||||
form.add_field("shareWorkflowIsNSFW", str(is_nsfw).lower())
|
||||
form.add_field("currentSnapshot", json.dumps(await core.get_current_snapshot()))
|
||||
form.add_field("modelsInfo", json.dumps(models_info))
|
||||
|
||||
async with session.post(
|
||||
f"{share_endpoint}/upload_workflow",
|
||||
data=form,
|
||||
) as resp:
|
||||
assert resp.status == 200
|
||||
upload_workflow_json = await resp.json()
|
||||
workflowId = upload_workflow_json["workflowId"]
|
||||
|
||||
# check if the user has provided Matrix credentials
|
||||
if "matrix" in share_destinations:
|
||||
comfyui_share_room_id = '!LGYSoacpJPhIfBqVfb:matrix.org'
|
||||
filename = os.path.basename(asset_filepath)
|
||||
content_type = assetFileType
|
||||
|
||||
try:
|
||||
from matrix_client.api import MatrixHttpApi
|
||||
from matrix_client.client import MatrixClient
|
||||
|
||||
homeserver = 'matrix.org'
|
||||
if matrix_auth:
|
||||
homeserver = matrix_auth.get('homeserver', 'matrix.org')
|
||||
homeserver = homeserver.replace("http://", "https://")
|
||||
if not homeserver.startswith("https://"):
|
||||
homeserver = "https://" + homeserver
|
||||
|
||||
client = MatrixClient(homeserver)
|
||||
try:
|
||||
token = client.login(username=matrix_auth['username'], password=matrix_auth['password'])
|
||||
if not token:
|
||||
return web.json_response({"error": "Invalid Matrix credentials."}, content_type='application/json', status=400)
|
||||
except:
|
||||
return web.json_response({"error": "Invalid Matrix credentials."}, content_type='application/json', status=400)
|
||||
|
||||
matrix = MatrixHttpApi(homeserver, token=token)
|
||||
with open(asset_filepath, 'rb') as f:
|
||||
mxc_url = matrix.media_upload(f.read(), content_type, filename=filename)['content_uri']
|
||||
|
||||
workflow_json_mxc_url = matrix.media_upload(prompt['workflow'], 'application/json', filename='workflow.json')['content_uri']
|
||||
|
||||
text_content = ""
|
||||
if title:
|
||||
text_content += f"{title}\n"
|
||||
if description:
|
||||
text_content += f"{description}\n"
|
||||
if credits:
|
||||
text_content += f"\ncredits: {credits}\n"
|
||||
matrix.send_message(comfyui_share_room_id, text_content)
|
||||
matrix.send_content(comfyui_share_room_id, mxc_url, filename, 'm.image')
|
||||
matrix.send_content(comfyui_share_room_id, workflow_json_mxc_url, 'workflow.json', 'm.file')
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return web.json_response({"error": "An error occurred when sharing your art to Matrix."}, content_type='application/json', status=500)
|
||||
|
||||
return web.json_response({
|
||||
"comfyworkflows": {
|
||||
"url": None if "comfyworkflows" not in share_destinations else f"{share_website_host}/workflows/{workflowId}",
|
||||
},
|
||||
"matrix": {
|
||||
"success": None if "matrix" not in share_destinations else True
|
||||
}
|
||||
}, content_type='application/json', status=200)
|
||||
@@ -12,10 +12,10 @@ import ast
|
||||
import logging
|
||||
import traceback
|
||||
|
||||
from .glob import security_check
|
||||
from .glob import manager_util
|
||||
from .glob import cm_global
|
||||
from .glob import manager_downloader
|
||||
from .common import security_check
|
||||
from .common import manager_util
|
||||
from .common import cm_global
|
||||
from .common import manager_downloader
|
||||
import folder_paths
|
||||
|
||||
manager_util.add_python_path_to_env()
|
||||
|
||||
@@ -1694,16 +1694,6 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "This node manipulates the pixel art image in ways that it should look pixel perfect (downscales, changes palette, upscales etc.)."
|
||||
},
|
||||
{
|
||||
"author": "hylarucoder",
|
||||
"title": "comfyui-copilot",
|
||||
"reference": "https://github.com/hylarucoder/comfyui-copilot",
|
||||
"files": [
|
||||
"https://github.com/hylarucoder/comfyui-copilot"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "NODES:Eagle Image Node for PNGInfo, SDXL Resolution Presets (ws), SDXL Prompt Styler, SDXL Prompt Styler Advanced"
|
||||
},
|
||||
{
|
||||
"author": "theUpsider",
|
||||
"title": "Styles CSV Loader Extension for ComfyUI",
|
||||
@@ -7741,6 +7731,16 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "A powerful ComfyUI custom node for combining video clips with synchronized audio, background music, and advanced audio controls."
|
||||
},
|
||||
{
|
||||
"author": "ShmuelRonen",
|
||||
"title": "ComfyUI-Veo2-Experimental",
|
||||
"reference": "https://github.com/ShmuelRonen/ComfyUI-Veo2-Experimental",
|
||||
"files": [
|
||||
"https://github.com/ShmuelRonen/ComfyUI-Veo2-Experimental"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A custom node extension for ComfyUI that integrates Google's Veo 2 text-to-video generation capabilities."
|
||||
},
|
||||
{
|
||||
"author": "redhottensors",
|
||||
"title": "ComfyUI-Prediction",
|
||||
@@ -7877,6 +7877,16 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI-SparkTTS is a custom ComfyUI node implementation of SparkTTS, an advanced text-to-speech system that harnesses the power of large language models (LLMs) to generate highly accurate and natural-sounding speech."
|
||||
},
|
||||
{
|
||||
"author": "1038lab",
|
||||
"title": "ComfyUI-MegaTTS",
|
||||
"reference": "https://github.com/1038lab/ComfyUI-MegaTTS",
|
||||
"files": [
|
||||
"https://github.com/1038lab/ComfyUI-MegaTTS"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A ComfyUI custom node based on ByteDance MegaTTS3 MegaTTS3, enabling high-quality text-to-speech synthesis with voice cloning capabilities for both Chinese and English."
|
||||
},
|
||||
{
|
||||
"author": "Klinter",
|
||||
"title": "Klinter_nodes",
|
||||
@@ -16524,9 +16534,9 @@
|
||||
{
|
||||
"author": "edelvarden",
|
||||
"title": "ComfyUI-ImageMetadataExtension",
|
||||
"reference": "https://github.com/edelvarden/ComfyUI-ImageMetadataExtension",
|
||||
"reference": "https://github.com/edelvarden/comfyui_image_metadata_extension",
|
||||
"files": [
|
||||
"https://github.com/edelvarden/ComfyUI-ImageMetadataExtension"
|
||||
"https://github.com/edelvarden/comfyui_image_metadata_extension"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom node for ComfyUI. It adds additional metadata for saved images, ensuring compatibility with the Civitai website."
|
||||
@@ -18904,6 +18914,16 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI nodes for SkyReels-A2 model."
|
||||
},
|
||||
{
|
||||
"author": "Yuan-ManX",
|
||||
"title": "ComfyUI-UNO",
|
||||
"reference": "https://github.com/Yuan-ManX/ComfyUI-UNO",
|
||||
"files": [
|
||||
"https://github.com/Yuan-ManX/ComfyUI-UNO"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI nodes for UNO model."
|
||||
},
|
||||
{
|
||||
"author": "Starnodes2024",
|
||||
"title": "ComfyUI_StarNodes",
|
||||
@@ -19366,6 +19386,16 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI_RH_OminiControl is a ComfyUI plugin based on OminiControl By splitting the pipeline load, the plugin efficiently runs on NVIDIA RTX 4090 GPUs. Additionally, the spatial and fill functionalities are generated using the schnell model, reducing the number of sampling steps and improving overall efficiency."
|
||||
},
|
||||
{
|
||||
"author": "HM-RunningHub",
|
||||
"title": "ComfyUI_RH_UNO",
|
||||
"reference": "https://github.com/HM-RunningHub/ComfyUI_RH_UNO",
|
||||
"files": [
|
||||
"https://github.com/HM-RunningHub/ComfyUI_RH_UNO"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "This is a UNO ComfyUI plugin implementation that can run the full version with 24GB VRAM, as well as quickly run the FP8 version."
|
||||
},
|
||||
{
|
||||
"author": "sebord",
|
||||
"title": "ComfyUI-LMCQ",
|
||||
@@ -20102,8 +20132,8 @@
|
||||
"description": "An extension for ComfyUI that adds utility functions and nodes not available in the default setup."
|
||||
},
|
||||
{
|
||||
"author": "billwuhao",
|
||||
"title": "ComfyUI_OneButtonPrompt",
|
||||
"author": "mw",
|
||||
"title": "MW-ComfyUI_OneButtonPrompt",
|
||||
"reference": "https://github.com/billwuhao/ComfyUI_OneButtonPrompt",
|
||||
"files": [
|
||||
"https://github.com/billwuhao/ComfyUI_OneButtonPrompt"
|
||||
@@ -20112,7 +20142,7 @@
|
||||
"description": "A node that assists in one click generation of prompts (for image and video generation, etc.) in Comfyui."
|
||||
},
|
||||
{
|
||||
"author": "billwuhao",
|
||||
"author": "mw",
|
||||
"title": "ComfyUI_StepAudioTTS",
|
||||
"reference": "https://github.com/billwuhao/ComfyUI_StepAudioTTS",
|
||||
"files": [
|
||||
@@ -20122,7 +20152,7 @@
|
||||
"description": "A Text To Speech node using Step-Audio-TTS in ComfyUI. Can speak, rap, sing, or clone voice."
|
||||
},
|
||||
{
|
||||
"author": "billwuhao",
|
||||
"author": "mw",
|
||||
"title": "ComfyUI_KokoroTTS_MW",
|
||||
"reference": "https://github.com/billwuhao/ComfyUI_KokoroTTS_MW",
|
||||
"files": [
|
||||
@@ -20132,8 +20162,8 @@
|
||||
"description": "A Text To Speech node using Kokoro TTS in ComfyUI. Supports 8 languages and 150 voices"
|
||||
},
|
||||
{
|
||||
"author": "billwuhao",
|
||||
"title": "ComfyUI_DiffRhythm",
|
||||
"author": "mw",
|
||||
"title": "ComfyUI_DiffRhythm_MW",
|
||||
"reference": "https://github.com/billwuhao/ComfyUI_DiffRhythm",
|
||||
"files": [
|
||||
"https://github.com/billwuhao/ComfyUI_DiffRhythm"
|
||||
@@ -20141,6 +20171,16 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "Blazingly Fast and Embarrassingly Simple End-to-End Full-Length Song Generation. A node for ComfyUI."
|
||||
},
|
||||
{
|
||||
"author": "mw",
|
||||
"title": "MW-ComfyUI_PortraitTools",
|
||||
"reference": "https://github.com/billwuhao/ComfyUI_PortraitTools",
|
||||
"files": [
|
||||
"https://github.com/billwuhao/ComfyUI_PortraitTools"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Portrait Tools: Facial detection cropping, alignment, ID photo, etc."
|
||||
},
|
||||
{
|
||||
"author": "mw",
|
||||
"title": "ComfyUI_NotaGen",
|
||||
@@ -20891,6 +20931,16 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom nodes for ComfyUI designed for cropping and stitching video frames (image batches). Part of the 'Burgstall Enabling The Awesomeness' suite."
|
||||
},
|
||||
{
|
||||
"author": "Burgstall-labs",
|
||||
"title": "ComfyUI-BETA-Helpernodes",
|
||||
"reference": "https://github.com/Burgstall-labs/ComfyUI-BETA-Helpernodes",
|
||||
"files": [
|
||||
"hhttps://github.com/Burgstall-labs/ComfyUI-BETA-Helpernodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom utility nodes for ComfyUI, providing helpers for tasks like video frame manipulation and advanced audio saving. Part of the 'Burgstall Enabling The Awesomeness' suite."
|
||||
},
|
||||
{
|
||||
"author": "Kidev",
|
||||
"title": "ComfyUI Fisheye Effects Nodes",
|
||||
@@ -21748,6 +21798,17 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "Advanced LLM driven node with many custom instructions, including node finder, expert prompter and json converter."
|
||||
},
|
||||
{
|
||||
"author": "lum3on",
|
||||
"title": "HiDream Sampler",
|
||||
"id": "hidream-sampler",
|
||||
"reference": "https://github.com/lum3on/comfyui_HiDream-Sampler",
|
||||
"files": [
|
||||
"https://github.com/lum3on/comfyui_HiDream-Sampler"
|
||||
],
|
||||
"install_type": "copy",
|
||||
"description": "A custom ComfyUI node for generating images using the HiDream AI model. Uses quantization for lower memory usage."
|
||||
},
|
||||
{
|
||||
"author": "austinbrown34",
|
||||
"title": "ComfyUI-IO-Helpers",
|
||||
@@ -22446,9 +22507,9 @@
|
||||
{
|
||||
"author": "ifmylove2011",
|
||||
"title": "comfyui-missing-tool",
|
||||
"reference": "https://github.com/ifmylove2011/comfyui-missing-tool",
|
||||
"reference": "https://github.com/ifmylove2011/comfyui-missed-tool",
|
||||
"files": [
|
||||
"https://github.com/ifmylove2011/comfyui-missing-tool"
|
||||
"https://github.com/ifmylove2011/comfyui-missed-tool"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "NODES: TrimBG, TrimBG Advanced, Image Queue Loader, Load Image Alpha.\nA few tools for ComfyUI, perhaps it's exactly what you need."
|
||||
@@ -23128,6 +23189,16 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI node to vectorize images using the pure Python 'potracer' library."
|
||||
},
|
||||
{
|
||||
"author": "ImagineerNL",
|
||||
"title": "ComfyUI-IMGNR-Utils",
|
||||
"reference": "https://github.com/ImagineerNL/ComfyUI-IMGNR-Utils",
|
||||
"files": [
|
||||
"https://github.com/ImagineerNL/ComfyUI-IMGNR-Utils"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI Utility Nodes by Imagineer. Currently 1: Catch and Edit Text, useful for grabbing AI generated prompts which you edit by hand. Doing so mutes the upstream node, improving speed and saving external calls and budget."
|
||||
},
|
||||
{
|
||||
"author": "Yushan777",
|
||||
"title": "Y7Nodes for ComfyUI",
|
||||
@@ -23492,6 +23563,17 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "This Module provides nodes to allow the development of 3D Generative AI workflows that use the MasterpieceX Python SDK."
|
||||
},
|
||||
{
|
||||
"author": "jerrywap",
|
||||
"title": "ComfyUI_LoadImageFromHttpURL",
|
||||
"id": "load-image-from-http-url",
|
||||
"reference": "https://github.com/jerrywap/ComfyUI_LoadImageFromHttpURL",
|
||||
"files": [
|
||||
"https://github.com/jerrywap/ComfyUI_LoadImageFromHttpURL"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A ComfyUI node that fetches an image from an HTTP URL and returns it as an image tensor. Useful for API-based workflows."
|
||||
},
|
||||
{
|
||||
"author": "jerrywap",
|
||||
"title": "ComfyUI_UploadToWebhookHTTP",
|
||||
@@ -23595,7 +23677,77 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "This node package contains automatic sampler setting according to model name in ComfyUI, adjusting image size according to specific constraints and some other nodes."
|
||||
},
|
||||
|
||||
{
|
||||
"author": "brantje",
|
||||
"title": "ComfyUI-api-tools",
|
||||
"id": "comfyui_api_tools",
|
||||
"reference": "https://github.com/brantje/ComfyUI-api-tools",
|
||||
"files": [
|
||||
"https://github.com/brantje/ComfyUI-api-tools"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Adds extra API functionallity and prometheus endpoint"
|
||||
},
|
||||
{
|
||||
"author": "oshtz",
|
||||
"title": "oshtz Nodes",
|
||||
"reference": "https://github.com/oshtz/ComfyUI-oshtz-nodes",
|
||||
"files": [
|
||||
"https://github.com/oshtz/ComfyUI-oshtz-nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom ComfyUI nodes including LLM integration, LoRA switchers, image tools, and more"
|
||||
},
|
||||
{
|
||||
"author": "HavocsCall",
|
||||
"title": "HavocsCall's Custom ComfyUI Nodes",
|
||||
"reference": "https://github.com/HavocsCall/comfyui_HavocsCall_Custom_Nodes",
|
||||
"files": [
|
||||
"https://github.com/HavocsCall/comfyui_HavocsCall_Custom_Nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "NODES: Prompt Combiner, Float/Int Selector, Sampler Config, Text Box, Int to Float/String, Int to Float/String, Clip/Conditioning/Image/Latent/Model/String/VAE Switch"
|
||||
},
|
||||
{
|
||||
"author": "danger-electrodes",
|
||||
"title": "ComfyUI_Fawfluencer_Nodes",
|
||||
"reference": "https://github.com/danger-electrodes/ComfyUI_Fawfluencer_Nodes",
|
||||
"files": [
|
||||
"https://github.com/danger-electrodes/ComfyUI_Fawfluencer_Nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A set of node for ComfyUI to create an influencer"
|
||||
},
|
||||
{
|
||||
"author": "badxprogramm",
|
||||
"title": "GradientBlurNode for ComfyUI",
|
||||
"reference": "https://github.com/badxprogramm/ComfyUI-GradientBlur",
|
||||
"files": [
|
||||
"https://github.com/badxprogramm/ComfyUI-GradientBlur"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "GradientBlurNode is a custom node for ComfyUI that allows for gradient-based image blurring. This tool provides precise control over the direction, intensity, and distribution of the blur, making it ideal for creating smooth transitions, focusing attention on specific parts of an image, or adding artistic effects."
|
||||
},
|
||||
{
|
||||
"author": "linksluckytime",
|
||||
"title": "comfyui_snacknodes",
|
||||
"reference": "https://github.com/linksluckytime/comfyui_snacknodes",
|
||||
"files": [
|
||||
"https://github.com/linksluckytime/comfyui_snacknodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A collection of custom nodes for ComfyUI"
|
||||
},
|
||||
{
|
||||
"author": "uihp",
|
||||
"title": "ComfyUI-String-Chain",
|
||||
"reference": "https://github.com/uihp/ComfyUI-String-Chain",
|
||||
"files": [
|
||||
"https://github.com/uihp/ComfyUI-String-Chain"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "String Chain: Reconnect your prompts"
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -67,6 +67,16 @@
|
||||
"title_aux": "ComfyUI-EdgeTTS"
|
||||
}
|
||||
],
|
||||
"https://github.com/1038lab/ComfyUI-MegaTTS": [
|
||||
[
|
||||
"MegaTTS3",
|
||||
"MegaTTS3S",
|
||||
"MegaTTS_VoiceMaker"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-MegaTTS"
|
||||
}
|
||||
],
|
||||
"https://github.com/1038lab/ComfyUI-OmniGen": [
|
||||
[
|
||||
"ailab_OmniGen"
|
||||
@@ -1577,28 +1587,10 @@
|
||||
"EXPORT (JOV) \ud83d\udcfd",
|
||||
"FILTER MASK (JOV) \ud83e\udd3f",
|
||||
"FLATTEN (JOV) \u2b07\ufe0f",
|
||||
"GLSL (JOV) \ud83c\udf69",
|
||||
"GLSL BLEND LINEAR (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL COLOR CONVERSION (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL COLOR PALETTE (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL CONICAL GRADIENT (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL DIRECTIONAL WARP (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL FILTER RANGE (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL GRAYSCALE (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL HSV ADJUST (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL INVERT (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL NORMAL (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL NORMAL BLEND (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL POSTERIZE (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL TRANSFORM (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GRADIENT MAP (JOV) \ud83c\uddf2\ud83c\uddfa",
|
||||
"GRAPH (JOV) \ud83d\udcc8",
|
||||
"IMAGE INFO (JOV) \ud83d\udcda",
|
||||
"LERP (JOV) \ud83d\udd30",
|
||||
"MIDI FILTER (JOV) \u2733\ufe0f",
|
||||
"MIDI FILTER EZ (JOV) \u2747\ufe0f",
|
||||
"MIDI MESSAGE (JOV) \ud83c\udf9b\ufe0f",
|
||||
"MIDI READER (JOV) \ud83c\udfb9",
|
||||
"OP BINARY (JOV) \ud83c\udf1f",
|
||||
"OP UNARY (JOV) \ud83c\udfb2",
|
||||
"PIXEL MERGE (JOV) \ud83e\udec2",
|
||||
@@ -1609,12 +1601,9 @@
|
||||
"ROUTE (JOV) \ud83d\ude8c",
|
||||
"SAVE OUTPUT (JOV) \ud83d\udcbe",
|
||||
"SHAPE GEN (JOV) \u2728",
|
||||
"SPOUT WRITER (JOV) \ud83c\udfa5",
|
||||
"STACK (JOV) \u2795",
|
||||
"STEREOGRAM (JOV) \ud83d\udcfb",
|
||||
"STEREOSCOPIC (JOV) \ud83d\udd76\ufe0f",
|
||||
"STREAM READER (JOV) \ud83d\udcfa",
|
||||
"STREAM WRITER (JOV) \ud83c\udf9e\ufe0f",
|
||||
"STRINGER (JOV) \ud83e\ude80",
|
||||
"SWIZZLE (JOV) \ud83d\ude35",
|
||||
"TEXT GEN (JOV) \ud83d\udcdd",
|
||||
@@ -2396,7 +2385,8 @@
|
||||
"https://github.com/Burgstall-labs/ComfyUI-BETA-Cropnodes": [
|
||||
[
|
||||
"BETACrop",
|
||||
"BETAStitch"
|
||||
"BETAStitch",
|
||||
"SaveAudioAdvanced_BETA"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-BETA-Cropnodes"
|
||||
@@ -2658,6 +2648,7 @@
|
||||
"CLIPTextEncodeFluxUnguided",
|
||||
"ClownRegionalConditioning",
|
||||
"ClownRegionalConditioning3",
|
||||
"ClownRegionalConditioning_AB",
|
||||
"ClownScheduler",
|
||||
"ClownpileModelWanVideo",
|
||||
"Conditioning Recast FP64",
|
||||
@@ -2777,6 +2768,7 @@
|
||||
"Tan Scheduler 2",
|
||||
"Tan Scheduler 2 Simple",
|
||||
"TemporalMaskGenerator",
|
||||
"TemporalSplitAttnMask",
|
||||
"TextBox1",
|
||||
"TextBox2",
|
||||
"TextBox3",
|
||||
@@ -2993,6 +2985,7 @@
|
||||
"DynamicVAESwitch",
|
||||
"EvaluaterNode",
|
||||
"Modelswitch",
|
||||
"PeopleEvaluationNode",
|
||||
"SanitizeFilename",
|
||||
"SystemPromp",
|
||||
"Textswitch",
|
||||
@@ -4635,6 +4628,15 @@
|
||||
"title_aux": "ComfyUI_RH_OminiControl"
|
||||
}
|
||||
],
|
||||
"https://github.com/HM-RunningHub/ComfyUI_RH_UNO": [
|
||||
[
|
||||
"RunningHub_UNO_Loadmodel",
|
||||
"RunningHub_UNO_Sampler"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_RH_UNO"
|
||||
}
|
||||
],
|
||||
"https://github.com/Haiper-ai/ComfyUI-HaiperAI-API": [
|
||||
[
|
||||
"HaiperImage2Video",
|
||||
@@ -4719,6 +4721,29 @@
|
||||
"title_aux": "ComfyUI ReSharpen"
|
||||
}
|
||||
],
|
||||
"https://github.com/HavocsCall/comfyui_HavocsCall_Custom_Nodes": [
|
||||
[
|
||||
"Clip Switch",
|
||||
"Conditioning Switch",
|
||||
"Float Selector",
|
||||
"Float to Int",
|
||||
"Float to String",
|
||||
"Image Switch",
|
||||
"Int Selector",
|
||||
"Int to Float",
|
||||
"Int to String",
|
||||
"Latent Switch",
|
||||
"Model Switch",
|
||||
"Prompt Combiner",
|
||||
"Sampler Config",
|
||||
"String Switch",
|
||||
"Text Box",
|
||||
"VAE Switch"
|
||||
],
|
||||
{
|
||||
"title_aux": "HavocsCall's Custom ComfyUI Nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/HaydenReeve/ComfyUI-Better-Strings": [
|
||||
[
|
||||
"BetterString"
|
||||
@@ -4944,6 +4969,14 @@
|
||||
"title_aux": "Simple String Repository"
|
||||
}
|
||||
],
|
||||
"https://github.com/ImagineerNL/ComfyUI-IMGNR-Utils": [
|
||||
[
|
||||
"CatchEditTextNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-IMGNR-Utils"
|
||||
}
|
||||
],
|
||||
"https://github.com/ImagineerNL/ComfyUI-ToSVG-Potracer": [
|
||||
[
|
||||
"PotracerVectorize"
|
||||
@@ -5497,8 +5530,15 @@
|
||||
"https://github.com/Jokimbe/ComfyUI-DrawThings-gRPC": [
|
||||
[
|
||||
"DrawThingsControlNet",
|
||||
"DrawThingsHighResFix",
|
||||
"DrawThingsLoRA",
|
||||
"DrawThingsSampler"
|
||||
"DrawThingsNegative",
|
||||
"DrawThingsPositive",
|
||||
"DrawThingsRefiner",
|
||||
"DrawThingsSampler",
|
||||
"DrawThingsTeaCache",
|
||||
"DrawThingsUpscaler",
|
||||
"DrawThingsVideo"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-DrawThings-gRPC"
|
||||
@@ -6934,6 +6974,7 @@
|
||||
[
|
||||
"iToolsAddOverlay",
|
||||
"iToolsCheckerBoard",
|
||||
"iToolsCompareImage",
|
||||
"iToolsGridFiller",
|
||||
"iToolsKSampler",
|
||||
"iToolsLineLoader",
|
||||
@@ -7987,6 +8028,7 @@
|
||||
"FormatConcatStrings",
|
||||
"FormattingSingle",
|
||||
"FourierAnalysisNode",
|
||||
"ImageDifference",
|
||||
"MosaicEffectNode",
|
||||
"PWLoraNameCollector",
|
||||
"PWLoraSelector",
|
||||
@@ -8993,15 +9035,9 @@
|
||||
],
|
||||
"https://github.com/Shiba-2-shiba/comfyui-color-ascii-art-node": [
|
||||
[
|
||||
"ASCIIArtNode",
|
||||
"ASCIIArtNodev2",
|
||||
"ASCIIArtSinglefontNode"
|
||||
"ASCIIArtNodeV3"
|
||||
],
|
||||
{
|
||||
"author": "Shiba-2-shiba",
|
||||
"description": "This node generates colorful ASCII art using custom character sets and fonts.",
|
||||
"nickname": "ColorASCII",
|
||||
"title": "Colorful ASCII Art Node",
|
||||
"title_aux": "ComfyUI-color-ascii-art-node"
|
||||
}
|
||||
],
|
||||
@@ -9172,6 +9208,16 @@
|
||||
"title_aux": "ComfyUI-SVDResizer"
|
||||
}
|
||||
],
|
||||
"https://github.com/ShmuelRonen/ComfyUI-Veo2-Experimental": [
|
||||
[
|
||||
"VeoTextToVideo",
|
||||
"VeoToVHS",
|
||||
"VeoVideoPreview"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-Veo2-Experimental"
|
||||
}
|
||||
],
|
||||
"https://github.com/ShmuelRonen/ComfyUI-WanVideoKsampler": [
|
||||
[
|
||||
"WanVideoKsampler"
|
||||
@@ -9589,6 +9635,7 @@
|
||||
"SDVN AnyDownload List",
|
||||
"SDVN Apply Style Model",
|
||||
"SDVN Auto Generate",
|
||||
"SDVN AutoSwitch",
|
||||
"SDVN Boolean",
|
||||
"SDVN CLIP Download",
|
||||
"SDVN CLIP Text Encode",
|
||||
@@ -9634,6 +9681,7 @@
|
||||
"SDVN Load Lora",
|
||||
"SDVN Load Model",
|
||||
"SDVN Load Text",
|
||||
"SDVN LoadPinterest",
|
||||
"SDVN Logic",
|
||||
"SDVN Loop Inpaint Stitch",
|
||||
"SDVN Lora Download",
|
||||
@@ -11603,6 +11651,19 @@
|
||||
"title_aux": "ComfyUI-StyleStudio"
|
||||
}
|
||||
],
|
||||
"https://github.com/Yuan-ManX/ComfyUI-UNO": [
|
||||
[
|
||||
"ConfigSave",
|
||||
"ImageConcat",
|
||||
"ImagePathLoader",
|
||||
"ImageSave",
|
||||
"UNOGenerator",
|
||||
"UNOParams"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-UNO"
|
||||
}
|
||||
],
|
||||
"https://github.com/ZHO-ZHO-ZHO/ComfyUI-APISR": [
|
||||
[
|
||||
"APISR_Lterative_Zho",
|
||||
@@ -11997,7 +12058,8 @@
|
||||
"Rotate Module (Bending)",
|
||||
"Scale Module (Bending)",
|
||||
"Sobel Module (Bending)",
|
||||
"Threshold Module (Bending)"
|
||||
"Threshold Module (Bending)",
|
||||
"Visualize Feature Map"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI Model Bending"
|
||||
@@ -12322,6 +12384,7 @@
|
||||
"CogVideoXFunInpaintSampler",
|
||||
"CogVideoXFunT2VSampler",
|
||||
"CogVideoXFunV2VSampler",
|
||||
"FunRiflex",
|
||||
"FunTextBox",
|
||||
"LoadCogVideoXFunLora",
|
||||
"LoadCogVideoXFunModel",
|
||||
@@ -13202,6 +13265,14 @@
|
||||
"title_aux": "LoRA Tag Loader for ComfyUI"
|
||||
}
|
||||
],
|
||||
"https://github.com/badxprogramm/ComfyUI-GradientBlur": [
|
||||
[
|
||||
"GradientBlur"
|
||||
],
|
||||
{
|
||||
"title_aux": "GradientBlurNode for ComfyUI"
|
||||
}
|
||||
],
|
||||
"https://github.com/baicai99/ComfyUI-FrameSkipping": [
|
||||
[
|
||||
"FrameSelector",
|
||||
@@ -13562,7 +13633,7 @@
|
||||
"MultiLinePrompt"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_DiffRhythm"
|
||||
"title_aux": "ComfyUI_DiffRhythm_MW"
|
||||
}
|
||||
],
|
||||
"https://github.com/billwuhao/ComfyUI_EraX-WoW-Turbo": [
|
||||
@@ -13607,7 +13678,19 @@
|
||||
"LoadPrompt"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_OneButtonPrompt"
|
||||
"title_aux": "MW-ComfyUI_OneButtonPrompt"
|
||||
}
|
||||
],
|
||||
"https://github.com/billwuhao/ComfyUI_PortraitTools": [
|
||||
[
|
||||
"AlignFace",
|
||||
"BeautifyPhoto",
|
||||
"DetectCropFace",
|
||||
"IDPhotos",
|
||||
"RMBG"
|
||||
],
|
||||
{
|
||||
"title_aux": "MW-ComfyUI_PortraitTools"
|
||||
}
|
||||
],
|
||||
"https://github.com/billwuhao/ComfyUI_SparkTTS": [
|
||||
@@ -14008,6 +14091,14 @@
|
||||
"title_aux": "braintacles-nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/brantje/ComfyUI-api-tools": [
|
||||
[
|
||||
"SimpleGenImageInterface"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-api-tools"
|
||||
}
|
||||
],
|
||||
"https://github.com/brayevalerien/ComfyUI-resynthesizer": [
|
||||
[
|
||||
"Resynthesize"
|
||||
@@ -16320,6 +16411,7 @@
|
||||
"VPScheduler",
|
||||
"VideoLinearCFGGuidance",
|
||||
"VideoTriangleCFGGuidance",
|
||||
"VoxelToMesh",
|
||||
"VoxelToMeshBasic",
|
||||
"WanFunControlToVideo",
|
||||
"WanFunInpaintToVideo",
|
||||
@@ -16906,6 +16998,54 @@
|
||||
"title_aux": "SDXL Auto Prompter"
|
||||
}
|
||||
],
|
||||
"https://github.com/danger-electrodes/ComfyUI_Fawfluencer_Nodes": [
|
||||
[
|
||||
"FawfaceModelSpreadsheetRealismNode",
|
||||
"FawfakeAuthenticImageSaveNode",
|
||||
"FawfluxencerNode",
|
||||
"FawfulizedAddImagesToImageList",
|
||||
"FawfulizedEmptyImageList",
|
||||
"FawfulizedHunyuanAddNoise",
|
||||
"FawfulizedHunyuanBasicGuider",
|
||||
"FawfulizedHunyuanBasicScheduler",
|
||||
"FawfulizedHunyuanBetaSamplingScheduler",
|
||||
"FawfulizedHunyuanCFGGuider",
|
||||
"FawfulizedHunyuanControlNetApply",
|
||||
"FawfulizedHunyuanControlNetApplyAdvanced",
|
||||
"FawfulizedHunyuanControlNetLoader",
|
||||
"FawfulizedHunyuanDiffControlNetLoader",
|
||||
"FawfulizedHunyuanDisableNoise",
|
||||
"FawfulizedHunyuanDualCFGGuider",
|
||||
"FawfulizedHunyuanExponentialScheduler",
|
||||
"FawfulizedHunyuanFlipSigmas",
|
||||
"FawfulizedHunyuanKSamplerSelect",
|
||||
"FawfulizedHunyuanKarrasScheduler",
|
||||
"FawfulizedHunyuanLaplaceScheduler",
|
||||
"FawfulizedHunyuanLatentVideo",
|
||||
"FawfulizedHunyuanPolyexponentialScheduler",
|
||||
"FawfulizedHunyuanRandomNoise",
|
||||
"FawfulizedHunyuanSDTurboScheduler",
|
||||
"FawfulizedHunyuanSamplerCustom",
|
||||
"FawfulizedHunyuanSamplerCustomAdvanced",
|
||||
"FawfulizedHunyuanSamplerDPMAdaptative",
|
||||
"FawfulizedHunyuanSamplerDPMPP_2M_SDE",
|
||||
"FawfulizedHunyuanSamplerDPMPP_2S_Ancestral",
|
||||
"FawfulizedHunyuanSamplerDPMPP_3M_SDE",
|
||||
"FawfulizedHunyuanSamplerDPMPP_SDE",
|
||||
"FawfulizedHunyuanSamplerEulerAncestral",
|
||||
"FawfulizedHunyuanSamplerEulerAncestralCFGPP",
|
||||
"FawfulizedHunyuanSamplerLMS",
|
||||
"FawfulizedHunyuanSetFirstSigma",
|
||||
"FawfulizedHunyuanSetLatentNoiseMask",
|
||||
"FawfulizedHunyuanSplitSigmas",
|
||||
"FawfulizedHunyuanSplitSigmasDenoise",
|
||||
"FawfulizedHunyuanVPScheduler",
|
||||
"Img2ImgFawfluencerNodeSDXL"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_Fawfluencer_Nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/daniabib/ComfyUI_ProPainter_Nodes": [
|
||||
[
|
||||
"ProPainterInpaint",
|
||||
@@ -17678,7 +17818,7 @@
|
||||
"title_aux": "Semantic-SAM"
|
||||
}
|
||||
],
|
||||
"https://github.com/edelvarden/ComfyUI-ImageMetadataExtension": [
|
||||
"https://github.com/edelvarden/comfyui_image_metadata_extension": [
|
||||
[
|
||||
"CreateExtraMetaData",
|
||||
"SaveImageWithMetaData"
|
||||
@@ -18280,6 +18420,7 @@
|
||||
"FL_NodeLoader",
|
||||
"FL_NodePackLoader",
|
||||
"FL_OllamaCaptioner",
|
||||
"FL_PDFEncryptor",
|
||||
"FL_PDFImageExtractor",
|
||||
"FL_PDFLoader",
|
||||
"FL_PDFMerger",
|
||||
@@ -18290,6 +18431,7 @@
|
||||
"FL_PaperDrawn",
|
||||
"FL_PasteOnCanvas",
|
||||
"FL_PathTypeChecker",
|
||||
"FL_PixVerseAPI",
|
||||
"FL_PixelArtShader",
|
||||
"FL_PixelSort",
|
||||
"FL_ProResVideo",
|
||||
@@ -18311,6 +18453,7 @@
|
||||
"FL_SimpleGPTVision",
|
||||
"FL_SystemCheck",
|
||||
"FL_TetrisGame",
|
||||
"FL_TextToPDF",
|
||||
"FL_TimeLine",
|
||||
"FL_UpscaleModel",
|
||||
"FL_VideoCaptionSaver",
|
||||
@@ -18857,6 +19000,7 @@
|
||||
"ImgTextSwitch",
|
||||
"Load Remote Models",
|
||||
"LoadText|plush",
|
||||
"Model-CLIP Output Switch",
|
||||
"ParseJSON",
|
||||
"Plush-Exif Wrangler",
|
||||
"Random Image Output",
|
||||
@@ -20019,17 +20163,6 @@
|
||||
"title_aux": "ComfyUI-Select-Any"
|
||||
}
|
||||
],
|
||||
"https://github.com/hylarucoder/comfyui-copilot": [
|
||||
[
|
||||
"EagleImageNode",
|
||||
"SDXLPromptStyler",
|
||||
"SDXLPromptStylerAdvanced",
|
||||
"SDXLResolutionPresets"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-copilot"
|
||||
}
|
||||
],
|
||||
"https://github.com/hyunamy/comfy-ui-on-complete-email-me": [
|
||||
[
|
||||
"OnCompleteEmailMe",
|
||||
@@ -20240,12 +20373,17 @@
|
||||
"title_aux": "IF_AI_LoadImages"
|
||||
}
|
||||
],
|
||||
"https://github.com/ifmylove2011/comfyui-missing-tool": [
|
||||
"https://github.com/ifmylove2011/comfyui-missed-tool": [
|
||||
[
|
||||
"ImageQueueLoader",
|
||||
"LoadImageA",
|
||||
"LoraLoad",
|
||||
"LoraMerge",
|
||||
"LoraSaver",
|
||||
"ScaleMultilplePixels",
|
||||
"TrimBG",
|
||||
"TrimBGAdvanced"
|
||||
"TrimBGAdvanced",
|
||||
"TxtSave"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-missing-tool"
|
||||
@@ -20256,7 +20394,10 @@
|
||||
"Light-Tool: AddBackground",
|
||||
"Light-Tool: AddBackgroundV2",
|
||||
"Light-Tool: BoundingBoxCropping",
|
||||
"Light-Tool: Calculate",
|
||||
"Light-Tool: DeserializeJsonString",
|
||||
"Light-Tool: GetImageSize",
|
||||
"Light-Tool: GetImagesCount",
|
||||
"Light-Tool: Hex2Rgb",
|
||||
"Light-Tool: ImageConcat",
|
||||
"Light-Tool: ImageMaskApply",
|
||||
@@ -20270,6 +20411,7 @@
|
||||
"Light-Tool: LoadImage",
|
||||
"Light-Tool: LoadImageFromURL",
|
||||
"Light-Tool: LoadImagesFromDir",
|
||||
"Light-Tool: LoadMetadataFromURL",
|
||||
"Light-Tool: LoadVideo",
|
||||
"Light-Tool: MaskBoundingBoxCropping",
|
||||
"Light-Tool: MaskContourExtractor",
|
||||
@@ -20281,9 +20423,11 @@
|
||||
"Light-Tool: RGB2RGBA",
|
||||
"Light-Tool: RGBA2RGB",
|
||||
"Light-Tool: ResizeImage",
|
||||
"Light-Tool: SaveMetadata",
|
||||
"Light-Tool: SaveToAliyunOSS",
|
||||
"Light-Tool: SaveVideo",
|
||||
"Light-Tool: ScaleImage",
|
||||
"Light-Tool: SerializeJsonObject",
|
||||
"Light-Tool: ShowText",
|
||||
"Light-Tool: SimpleImageOverlay",
|
||||
"Light-Tool: SimpleTextConnect",
|
||||
@@ -20967,7 +21111,8 @@
|
||||
"EasyControlGenerate",
|
||||
"EasyControlLoadFlux",
|
||||
"EasyControlLoadLora",
|
||||
"EasyControlLoadMultiLora"
|
||||
"EasyControlLoadMultiLora",
|
||||
"EasyControlLoadStyleLora"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-easycontrol"
|
||||
@@ -21042,6 +21187,14 @@
|
||||
"title_aux": "ComfyUI-My-Mask"
|
||||
}
|
||||
],
|
||||
"https://github.com/jerrywap/ComfyUI_LoadImageFromHttpURL": [
|
||||
[
|
||||
"LoadImageFromHttpURL"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_LoadImageFromHttpURL"
|
||||
}
|
||||
],
|
||||
"https://github.com/jerrywap/ComfyUI_UploadToWebhookHTTP": [
|
||||
[
|
||||
"UploadToWebHookHTTP"
|
||||
@@ -21293,7 +21446,13 @@
|
||||
"https://github.com/joeriben/ai4artsed_comfyui": [
|
||||
[
|
||||
"ai4artsed_ollama",
|
||||
"ai4artsed_openrouter"
|
||||
"ai4artsed_ollama_imageanalysis",
|
||||
"ai4artsed_openrouter",
|
||||
"ai4artsed_openrouter_imageanalysis",
|
||||
"ai4artsed_random_artform_generator",
|
||||
"ai4artsed_random_instruction_generator",
|
||||
"ai4artsed_random_language_selector",
|
||||
"ai4artsed_text_remix"
|
||||
],
|
||||
{
|
||||
"title_aux": "AI4ArtsEd Ollama Prompt Node"
|
||||
@@ -23278,6 +23437,14 @@
|
||||
"title_aux": "comfyui_kj"
|
||||
}
|
||||
],
|
||||
"https://github.com/linksluckytime/comfyui_snacknodes": [
|
||||
[
|
||||
"SnackImageScaler"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui_snacknodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/linshier/comfyui-remote-tools": [
|
||||
[
|
||||
"LoadBase64(js)",
|
||||
@@ -25196,6 +25363,7 @@
|
||||
"CanvasCreatorAdvanced",
|
||||
"CanvasCreatorBasic",
|
||||
"CanvasCreatorSimple",
|
||||
"CheckpointLoaderSimpleMira",
|
||||
"CreateMaskWithCanvas",
|
||||
"CreateNestedPNGMask",
|
||||
"CreateSimpleMask",
|
||||
@@ -25221,6 +25389,7 @@
|
||||
"ImageHUE",
|
||||
"ImageRGBChannel",
|
||||
"ImageSaturation",
|
||||
"ImageSaverMira",
|
||||
"ImageSharpness",
|
||||
"ImageToneCurve",
|
||||
"IntMultiplication",
|
||||
@@ -25847,6 +26016,7 @@
|
||||
[
|
||||
"Nilor Categorize String",
|
||||
"Nilor Count Images In Directory",
|
||||
"Nilor Extract Filename from Path",
|
||||
"Nilor Int To List Of Bools",
|
||||
"Nilor Interpolated Float List",
|
||||
"Nilor Inverse Map Float List",
|
||||
@@ -26010,6 +26180,7 @@
|
||||
"https://github.com/nofunstudio/Node_Fun_ComfyUI": [
|
||||
[
|
||||
"DynamicQueueCounter",
|
||||
"Fun KSampler",
|
||||
"IframeView",
|
||||
"IndexedStringSelector",
|
||||
"LayeredInfiniteZoom",
|
||||
@@ -26312,6 +26483,19 @@
|
||||
"title_aux": "ComfyUI-wanBlockswap"
|
||||
}
|
||||
],
|
||||
"https://github.com/oshtz/ComfyUI-oshtz-nodes": [
|
||||
[
|
||||
"EasyAspectRatioNode",
|
||||
"LLMAIONode",
|
||||
"LoRASwitcherNode",
|
||||
"LoRASwitcherNode20",
|
||||
"LoRASwitcherNode40",
|
||||
"StringSplitterNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "oshtz Nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/osi1880vr/prompt_quill_comfyui": [
|
||||
[
|
||||
"PromptQuillGenerate",
|
||||
@@ -26980,6 +27164,7 @@
|
||||
],
|
||||
"https://github.com/rainlizard/ComfyUI-Raffle": [
|
||||
[
|
||||
"PreviewHistory",
|
||||
"Raffle"
|
||||
],
|
||||
{
|
||||
@@ -28373,7 +28558,6 @@
|
||||
"BizyAirSiliconCloudLLMAPI",
|
||||
"BizyAirSiliconCloudVLMAPI",
|
||||
"BizyAirTilePreprocessor",
|
||||
"BizyAirToggleServerEndpoint",
|
||||
"BizyAirUniFormer_SemSegPreprocessor",
|
||||
"BizyAirZoe_DepthMapPreprocessor",
|
||||
"BizyAir_MinusZoneChatGLM3TextEncode",
|
||||
@@ -30165,6 +30349,17 @@
|
||||
"title_aux": "comfyui-webcam-node"
|
||||
}
|
||||
],
|
||||
"https://github.com/uihp/ComfyUI-String-Chain": [
|
||||
[
|
||||
"String Chain",
|
||||
"String Concat",
|
||||
"String Toggle",
|
||||
"String Toggle (Multiline)"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-String-Chain"
|
||||
}
|
||||
],
|
||||
"https://github.com/umiyuki/comfyui-pad-to-eight": [
|
||||
[
|
||||
"Pad To Eight"
|
||||
@@ -30736,7 +30931,8 @@
|
||||
"Text_Match",
|
||||
"Whitening_Node",
|
||||
"YOLOWorld_Match",
|
||||
"YOLO_Crop"
|
||||
"YOLO_Crop",
|
||||
"YOLO_Multi_Crop"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_KimNodes"
|
||||
@@ -31282,6 +31478,7 @@
|
||||
"ImageRotate",
|
||||
"ImageSelector",
|
||||
"ImageUpscaleTiled",
|
||||
"LoadImagesFromFolder",
|
||||
"MaskBatchComposite",
|
||||
"MaskBatchCopy",
|
||||
"MaskContourFillNode",
|
||||
@@ -31295,7 +31492,8 @@
|
||||
"MaskTopNFilter",
|
||||
"TextBeforeKeyword",
|
||||
"YC Extract Number",
|
||||
"YC Text Index Switch"
|
||||
"YC Text Index Switch",
|
||||
"YC_Image_Save"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-YCNodes"
|
||||
@@ -31767,6 +31965,7 @@
|
||||
"https://github.com/yushan777/ComfyUI-Y7Nodes": [
|
||||
[
|
||||
"Y7Nodes_CLIP_TokenCounter",
|
||||
"Y7Nodes_CatchEditTextNodeDual",
|
||||
"Y7Nodes_Grid2Batch",
|
||||
"Y7Nodes_PromptEnhancerFlux",
|
||||
"Y7Nodes_ShowAnything",
|
||||
|
||||
5638
github-stats.json
5638
github-stats.json
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,77 @@
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"author": "hunzmusic",
|
||||
"title": "Comfyui-CraftsMan3DWrapper [WIP]",
|
||||
"reference": "https://github.com/hunzmusic/Comfyui-CraftsMan3DWrapper",
|
||||
"files": [
|
||||
"https://github.com/hunzmusic/Comfyui-CraftsMan3DWrapper"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A wrapper for CraftsMan\nNOTE: The files in the repo are not organized."
|
||||
},
|
||||
{
|
||||
"author": "jax-explorer",
|
||||
"title": "ComfyUI-H-flow",
|
||||
"reference": "https://github.com/jax-explorer/ComfyUI-H-flow",
|
||||
"files": [
|
||||
"https://github.com/jax-explorer/ComfyUI-H-flow"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "NODES: Wan2-1 Image To Video, LLM Task, Save Image, Save Video, Show Text, FluxPro Ultra, IdeogramV2 Turbo, Runway Image To Video, Kling Image To Video, Replace Text, Join Text, Test Image, Test Text"
|
||||
},
|
||||
{
|
||||
"author": "Slix-M-Lestragg",
|
||||
"title": "comfyui-enhanced [WIP]",
|
||||
"reference": "https://github.com/Slix-M-Lestragg/comfyui-enhanced",
|
||||
"files": [
|
||||
"https://github.com/Slix-M-Lestragg/comfyui-enhanced"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A collection of enhanced nodes for ComfyUI that provide powerful additional functionality to your workflows.\nNOTE: The files in the repo are not organized."
|
||||
},
|
||||
{
|
||||
"author": "tzsoulcap",
|
||||
"title": "ComfyUI-SaveImg-W-MetaData",
|
||||
"reference": "https://github.com/tzsoulcap/ComfyUI-SaveImg-W-MetaData",
|
||||
"files": [
|
||||
"https://github.com/tzsoulcap/ComfyUI-SaveImg-W-MetaData"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "NODES: CAP Checkpoint Selector, CAP Save Image w/Metadata, CAP Load Image with Metadata, CAP Tag Image, CAP Sampler Selector, CAP Scheduler Selector, CAP Seed Generator, CAP String Literal, CAP Width/Height Literal, CAP Cfg Literal, CAP Int Literal"
|
||||
},
|
||||
{
|
||||
"author": "hylarucoder",
|
||||
"title": "comfyui-copilot",
|
||||
"reference": "https://github.com/hylarucoder/comfyui-copilot",
|
||||
"files": [
|
||||
"https://github.com/hylarucoder/comfyui-copilot"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "NODES: Eagle Image Node for PNGInfo, SDXL Resolution Presets (ws), SDXL Prompt Styler, SDXL Prompt Styler Advanced"
|
||||
},
|
||||
{
|
||||
"author": "SS-snap",
|
||||
"title": "Comfyui_SSsnap_pose-Remapping",
|
||||
"reference": "https://github.com/SS-snap/Comfyui_SSsnap_pose-Remapping",
|
||||
"files": [
|
||||
"https://github.com/SS-snap/Comfyui_SSsnap_pose-Remapping"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "NODES: SSsnap Apply Pose Diff ✂️, SSsnap Pose Diff Calculator 🛠️"
|
||||
},
|
||||
{
|
||||
"author": "AlejandroTuzzi",
|
||||
"title": "TUZZI-ByPass [WIP]",
|
||||
"reference": "https://github.com/AlejandroTuzzi/TUZZI-ByPass",
|
||||
"files": [
|
||||
"https://github.com/AlejandroTuzzi/TUZZI-ByPass"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom nodes for automated AI pipelines\nNOTE: The files in the repo are not organized."
|
||||
},
|
||||
{
|
||||
"author": "oxysoft",
|
||||
"title": "Comfy-Compel",
|
||||
@@ -873,7 +944,7 @@
|
||||
"https://github.com/grinlau18/ComfyUI_XISER_Nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A collection of custom nodes for ComfyUI\nNOTE: The files in the repo are not organized."
|
||||
"description": "Custom nodes for customizing workflows\nNOTE: The files in the repo are not organized."
|
||||
},
|
||||
{
|
||||
"author": "LAOGOU-666",
|
||||
@@ -1624,7 +1695,7 @@
|
||||
"https://github.com/zyd232/ComfyUI-zyd232-Nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "NODES: Image Pixels Compare"
|
||||
"description": "NODES: Image Pixels Compare, Save Preview Images"
|
||||
},
|
||||
{
|
||||
"author": "yanhuifair",
|
||||
@@ -2563,16 +2634,6 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "NODES:LETM Save Image, ETM Load Image From Local"
|
||||
},
|
||||
{
|
||||
"author": "oshtz",
|
||||
"title": "ComfyUI-oshtz-nodes [WIP]",
|
||||
"reference": "https://github.com/oshtz/ComfyUI-oshtz-nodes",
|
||||
"files": [
|
||||
"https://github.com/oshtz/ComfyUI-oshtz-nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom nodes for ComfyUI created for some of my workflows.\nLLM All-in-One Node, String Splitter Node, LoRA Switcher Node, Image Overlay Node\nNOTE: The files in the repo are not organized."
|
||||
},
|
||||
{
|
||||
"author": "m-ai-studio",
|
||||
"title": "mai-prompt-progress",
|
||||
@@ -2854,16 +2915,6 @@
|
||||
"install_type": "copy",
|
||||
"description": "This platform extension provides ZhipuAI nodes, enabling you to configure a workflow for online video generation."
|
||||
},
|
||||
{
|
||||
"author": "HavocsCall",
|
||||
"title": "comfyui_HavocsCall_Custom_Nodes",
|
||||
"reference": "https://github.com/HavocsCall/comfyui_HavocsCall_Custom_Nodes",
|
||||
"files": [
|
||||
"https://github.com/HavocsCall/comfyui_HavocsCall_Custom_Nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "NODES:Prompt Combiner, Sampler Config, Text Box, Int to Float, Clip Switch, Conditioning Switch, Image Switch, Latent Switch, Model Switch, String Switch, VAE Switch"
|
||||
},
|
||||
{
|
||||
"author": "mfg637",
|
||||
"title": "ComfyUI-ScheduledGuider-Ext",
|
||||
|
||||
@@ -146,6 +146,59 @@
|
||||
"title_aux": "ComfyUI_Fooocus"
|
||||
}
|
||||
],
|
||||
"https://github.com/438443467/ComfyUI-SanMian-Nodes": [
|
||||
[
|
||||
"SANMIN Adapt Coordinates",
|
||||
"sanmi AddTextToImage",
|
||||
"sanmi Adjust Transparency By Mask",
|
||||
"sanmi AdjustHexBrightness",
|
||||
"sanmi Align Images with Mask",
|
||||
"sanmi BinarizeMask",
|
||||
"sanmi BlendICLight",
|
||||
"sanmi Chinese To Character",
|
||||
"sanmi Compare",
|
||||
"sanmi CompareV2",
|
||||
"sanmi Counter",
|
||||
"sanmi CreateTxtForImages",
|
||||
"sanmi Float",
|
||||
"sanmi Florence2toCoordinates",
|
||||
"sanmi Get Content From Excel",
|
||||
"sanmi Get LastPathComponent",
|
||||
"sanmi Get Mask White Region Size",
|
||||
"sanmi GetFilePath",
|
||||
"sanmi GetMostCommonColor",
|
||||
"sanmi ImageBatchSplitter",
|
||||
"sanmi Image_Rotate",
|
||||
"sanmi Int90",
|
||||
"sanmi IntToBOOLEAN",
|
||||
"sanmi Load Image Batch",
|
||||
"sanmi LoadImageFromPath",
|
||||
"sanmi LoadImagesanmi",
|
||||
"sanmi Mask To Box",
|
||||
"sanmi MaskToBboxes",
|
||||
"sanmi MaskWhiteRatioAnalyzer",
|
||||
"sanmi Path Captioner",
|
||||
"sanmi Path Change",
|
||||
"sanmi Read Image Prompt",
|
||||
"sanmi Reduce Mask",
|
||||
"sanmi RestoreJson",
|
||||
"sanmi Sanmi_Text_Concatenate",
|
||||
"sanmi Save Image To Local",
|
||||
"sanmi SimpleWildcards",
|
||||
"sanmi SortTheMasksLeftRight",
|
||||
"sanmi SortTheMasksSize",
|
||||
"sanmi Special Counter",
|
||||
"sanmi StrToPinYin",
|
||||
"sanmi String Counter",
|
||||
"sanmi String Counter V2",
|
||||
"sanmi StringToBox",
|
||||
"sanmi Time",
|
||||
"sanmi Upscale And Keep Original Size"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-SanMian-Nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/5x00/ComfyUI-Prompt-Plus": [
|
||||
[
|
||||
"LoadAPI",
|
||||
@@ -164,13 +217,17 @@
|
||||
],
|
||||
"https://github.com/7BEII/Comfyui_PDuse": [
|
||||
[
|
||||
"BatchChangeNodeColor",
|
||||
"BatchJsonIncremental",
|
||||
"FileName_refixer",
|
||||
"PD_ImageConcanate",
|
||||
"LoRALoader_path",
|
||||
"PD_GetImageSize",
|
||||
"PD_Image_Crop_Location",
|
||||
"PD_Image_centerCrop",
|
||||
"PD_MASK_SELECTION",
|
||||
"PD_RemoveColorWords",
|
||||
"ReadTxtFiles",
|
||||
"json_group_fontsize"
|
||||
"PD_node",
|
||||
"ReadTxtFiles"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-promptbymood [WIP]"
|
||||
@@ -452,6 +509,24 @@
|
||||
"title_aux": "ComfyUI-Tools"
|
||||
}
|
||||
],
|
||||
"https://github.com/AlejandroTuzzi/TUZZI-ByPass": [
|
||||
[
|
||||
"TUZZI-Bypasser",
|
||||
"TUZZI-ImageAudioToVideo",
|
||||
"TUZZI-LineCounter",
|
||||
"TUZZI-NumberLines",
|
||||
"TUZZI-RedditPostExtractor",
|
||||
"TUZZI-SaveVideo",
|
||||
"TUZZI-SequentialTextReader",
|
||||
"TUZZI-TextFormatter",
|
||||
"TUZZI-TextFormatterPlus",
|
||||
"TUZZI-YouTubeCommentExtractor",
|
||||
"TUZZI-YouTubeSubtitleExtractor"
|
||||
],
|
||||
{
|
||||
"title_aux": "TUZZI-ByPass [WIP]"
|
||||
}
|
||||
],
|
||||
"https://github.com/AlexXi19/ComfyUI-OpenAINode": [
|
||||
[
|
||||
"ImageWithPrompt",
|
||||
@@ -678,7 +753,10 @@
|
||||
],
|
||||
"https://github.com/Burgstall-labs/ComfyUI-BS_FalAi-API-Video": [
|
||||
[
|
||||
"FalAPIVideoGenerator"
|
||||
"FalAILipSyncNode",
|
||||
"FalAPIOmniProNode",
|
||||
"FalAPIVideoGeneratorI2V",
|
||||
"FalAPIVideoGeneratorT2V"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-BS_FalAi-API-Video [WIP]"
|
||||
@@ -695,6 +773,7 @@
|
||||
"https://github.com/Chargeuk/ComfyUI-vts-nodes": [
|
||||
[
|
||||
"VTS Clean Text",
|
||||
"VTS Clear Ram",
|
||||
"VTS Clip Text Encode",
|
||||
"VTS Color Mask To Mask",
|
||||
"VTS Conditioning Set Batch Mask",
|
||||
@@ -753,6 +832,7 @@
|
||||
"DevToolsLongComboDropdown",
|
||||
"DevToolsMultiSelectNode",
|
||||
"DevToolsNodeWithBooleanInput",
|
||||
"DevToolsNodeWithDefaultInput",
|
||||
"DevToolsNodeWithForceInput",
|
||||
"DevToolsNodeWithOnlyOptionalInput",
|
||||
"DevToolsNodeWithOptionalComboInput",
|
||||
@@ -858,7 +938,8 @@
|
||||
[
|
||||
"Donut Detailer",
|
||||
"Donut Detailer 2",
|
||||
"Donut Detailer 4"
|
||||
"Donut Detailer 4",
|
||||
"Donut Detailer LoRA 6"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-DonutDetailer"
|
||||
@@ -1077,30 +1158,6 @@
|
||||
"title_aux": "GH Tools for ComfyUI"
|
||||
}
|
||||
],
|
||||
"https://github.com/HavocsCall/comfyui_HavocsCall_Custom_Nodes": [
|
||||
[
|
||||
"Clip Switch",
|
||||
"Conditioning Switch",
|
||||
"Float Selector",
|
||||
"Float to Int",
|
||||
"Float to String",
|
||||
"Image Switch",
|
||||
"Int Selector",
|
||||
"Int to Float",
|
||||
"Int to String",
|
||||
"Latent Switch",
|
||||
"Model Switch",
|
||||
"Prompt Combiner",
|
||||
"Sampler Config",
|
||||
"String Switch",
|
||||
"Text Box",
|
||||
"VAE Switch",
|
||||
"menus"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui_HavocsCall_Custom_Nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/HuangYuChuh/ComfyUI-DeepSeek-Toolkit": [
|
||||
[
|
||||
"DeepSeekImageAnalyst",
|
||||
@@ -1203,9 +1260,7 @@
|
||||
],
|
||||
"https://github.com/KERRY-YUAN/ComfyUI_Python_Executor": [
|
||||
[
|
||||
"NodeAutoSampler",
|
||||
"NodePython",
|
||||
"NodeResizeImage"
|
||||
"NodePython"
|
||||
],
|
||||
{
|
||||
"title_aux": "Python_Executor [UNSAFE]"
|
||||
@@ -1276,6 +1331,17 @@
|
||||
"title_aux": "RK_Comfyui"
|
||||
}
|
||||
],
|
||||
"https://github.com/Kur0butiMegane/Comfyui-StringUtils": [
|
||||
[
|
||||
"ExtractMarkupValue",
|
||||
"PromptNormalizer",
|
||||
"StringSelector",
|
||||
"StringSplitter"
|
||||
],
|
||||
{
|
||||
"title_aux": "Comfyui-StringUtils"
|
||||
}
|
||||
],
|
||||
"https://github.com/KurtHokke/ComfyUI_KurtHokke_Nodes": [
|
||||
[
|
||||
"AIO_Tuner_Pipe",
|
||||
@@ -1390,14 +1456,20 @@
|
||||
"AnimalPosePreprocessor",
|
||||
"AnimeFace_SemSegPreprocessor",
|
||||
"AnimeLineArtPreprocessor",
|
||||
"AnyLineArtPreprocessor_aux",
|
||||
"BAE-NormalMapPreprocessor",
|
||||
"BinaryPreprocessor",
|
||||
"CannyEdgePreprocessor",
|
||||
"ColorPreprocessor",
|
||||
"ControlNetAuxSimpleAddText",
|
||||
"ControlNetPreprocessorSelector",
|
||||
"DSINE-NormalMapPreprocessor",
|
||||
"DWPreprocessor",
|
||||
"DensePosePreprocessor",
|
||||
"DepthAnythingPreprocessor",
|
||||
"DepthAnythingV2Preprocessor",
|
||||
"DiffusionEdge_Preprocessor",
|
||||
"ExecuteAllControlNetPreprocessors",
|
||||
"FacialPartColoringFromPoseKps",
|
||||
"FakeScribblePreprocessor",
|
||||
"HEDPreprocessor",
|
||||
@@ -1422,7 +1494,11 @@
|
||||
"Manga2Anime_LineArt_Preprocessor",
|
||||
"MaskOptFlow",
|
||||
"MediaPipe-FaceMeshPreprocessor",
|
||||
"MeshGraphormer+ImpactDetector-DepthMapPreprocessor",
|
||||
"MeshGraphormer-DepthMapPreprocessor",
|
||||
"Metric3D-DepthMapPreprocessor",
|
||||
"Metric3D-NormalMapPreprocessor",
|
||||
"Metric_DepthAnythingV2Preprocessor",
|
||||
"MiDaS-DepthMapPreprocessor",
|
||||
"MiDaS-NormalMapPreprocessor",
|
||||
"ModelMergeBlockNumber",
|
||||
@@ -1436,19 +1512,26 @@
|
||||
"PiDiNetPreprocessor",
|
||||
"PixelPerfectResolution",
|
||||
"PromptExpansion",
|
||||
"PyraCannyPreprocessor",
|
||||
"ReferenceOnlySimple",
|
||||
"RenderAnimalKps",
|
||||
"RenderPeopleKps",
|
||||
"RescaleClassifierFreeGuidanceTest",
|
||||
"SAMPreprocessor",
|
||||
"SavePoseKpsAsJsonFile",
|
||||
"ScribblePreprocessor",
|
||||
"Scribble_PiDiNet_Preprocessor",
|
||||
"Scribble_XDoG_Preprocessor",
|
||||
"SemSegPreprocessor",
|
||||
"ShufflePreprocessor",
|
||||
"TEEDPreprocessor",
|
||||
"TTPlanet_TileGF_Preprocessor",
|
||||
"TTPlanet_TileSimple_Preprocessor",
|
||||
"TilePreprocessor",
|
||||
"TonemapNoiseWithRescaleCFG",
|
||||
"UniFormer-SemSegPreprocessor",
|
||||
"Unimatch_OptFlowPreprocessor",
|
||||
"UpperBodyTrackingFromPoseKps",
|
||||
"Zoe-DepthMapPreprocessor",
|
||||
"Zoe_DepthAnythingPreprocessor"
|
||||
],
|
||||
@@ -1695,6 +1778,16 @@
|
||||
"title_aux": "ComfyUI-FRED-Nodes [WIP]"
|
||||
}
|
||||
],
|
||||
"https://github.com/QingLuanWithoutHeart/comfyui-file-image-utils": [
|
||||
[
|
||||
"FileManagerV2",
|
||||
"IfTextEquals",
|
||||
"LoadImageFromPath"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI File/Image Utils Nodes [UNSAFE]"
|
||||
}
|
||||
],
|
||||
"https://github.com/Quasimondo/ComfyUI-QuasimondoNodes": [
|
||||
[
|
||||
"CPPN Generator",
|
||||
@@ -1783,6 +1876,15 @@
|
||||
"title_aux": "Snap Processing for Comfyui"
|
||||
}
|
||||
],
|
||||
"https://github.com/SS-snap/Comfyui_SSsnap_pose-Remapping": [
|
||||
[
|
||||
"ApplyPoseDiff",
|
||||
"PoseDiffCalculator"
|
||||
],
|
||||
{
|
||||
"title_aux": "Comfyui_SSsnap_pose-Remapping"
|
||||
}
|
||||
],
|
||||
"https://github.com/SadaleNet/ComfyUI-Prompt-To-Prompt": [
|
||||
[
|
||||
"CLIPTextEncodePromptToPrompt",
|
||||
@@ -1903,6 +2005,14 @@
|
||||
"title_aux": "ComfyUI-FreeMemory"
|
||||
}
|
||||
],
|
||||
"https://github.com/Slix-M-Lestragg/comfyui-enhanced": [
|
||||
[
|
||||
"Range Iterator"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-enhanced [WIP]"
|
||||
}
|
||||
],
|
||||
"https://github.com/SoftMeng/ComfyUI-PIL": [
|
||||
[
|
||||
"PIL Effects (Mexx)",
|
||||
@@ -2030,6 +2140,14 @@
|
||||
"title_aux": "ComfyUI-TSFNodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/Temult/TWanSigmaSampler": [
|
||||
[
|
||||
"TWanVideoSigmaSampler"
|
||||
],
|
||||
{
|
||||
"title_aux": "TWanVideoSigmaSampler: EXPERIMENTAL [WIP]"
|
||||
}
|
||||
],
|
||||
"https://github.com/ThisModernDay/ComfyUI-InstructorOllama": [
|
||||
[
|
||||
"OllamaInstructorNode"
|
||||
@@ -2255,6 +2373,18 @@
|
||||
"title_aux": "ComfyUI-Diffusion-4k [WIP]"
|
||||
}
|
||||
],
|
||||
"https://github.com/alexgenovese/ComfyUI-Reica": [
|
||||
[
|
||||
"ReicaGCPReadImageNode",
|
||||
"ReicaGCPWriteImageNode",
|
||||
"ReicaHTTPNotification",
|
||||
"ReicaReadImageUrl",
|
||||
"ReicaTextImageDisplay"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-Reica"
|
||||
}
|
||||
],
|
||||
"https://github.com/alexisrolland/ComfyUI-AuraSR": [
|
||||
[
|
||||
"LoadAuraSR",
|
||||
@@ -2779,7 +2909,7 @@
|
||||
"https://github.com/chetusangolgi/Comfyui-supabase": [
|
||||
[
|
||||
"SupabaseImageUploader",
|
||||
"SupabaseWatcherNode"
|
||||
"SupabaseTableWatcherNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "Comfyui-supabase"
|
||||
@@ -3128,6 +3258,7 @@
|
||||
"VPScheduler",
|
||||
"VideoLinearCFGGuidance",
|
||||
"VideoTriangleCFGGuidance",
|
||||
"VoxelToMesh",
|
||||
"VoxelToMeshBasic",
|
||||
"WanFunControlToVideo",
|
||||
"WanFunInpaintToVideo",
|
||||
@@ -3561,7 +3692,8 @@
|
||||
"https://github.com/gondar-software/comfyui-custom-padding": [
|
||||
[
|
||||
"AdaptiveImagePadding",
|
||||
"AdaptiveImageUnpadding"
|
||||
"AdaptiveImageUnpadding",
|
||||
"WatermarkBlend"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-custom-padding"
|
||||
@@ -3885,6 +4017,17 @@
|
||||
"title_aux": "comfyui-hydit"
|
||||
}
|
||||
],
|
||||
"https://github.com/hylarucoder/comfyui-copilot": [
|
||||
[
|
||||
"EagleImageNode",
|
||||
"SDXLPromptStyler",
|
||||
"SDXLPromptStylerAdvanced",
|
||||
"SDXLResolutionPresets"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-copilot"
|
||||
}
|
||||
],
|
||||
"https://github.com/if-ai/ComfyUI-IF_Zonos": [
|
||||
[
|
||||
"IF_ZonosTTS"
|
||||
@@ -3962,6 +4105,21 @@
|
||||
"title_aux": "ComfyUI PaintingCoderUtils Nodes [WIP]"
|
||||
}
|
||||
],
|
||||
"https://github.com/jax-explorer/ComfyUI-H-flow": [
|
||||
[
|
||||
"FluxProUltra",
|
||||
"IdeogramV2Turbo",
|
||||
"KlingImageToVideo",
|
||||
"LLMTask",
|
||||
"RunwayImageToVideo",
|
||||
"SaveImage",
|
||||
"SaveVideo",
|
||||
"Wan2ImageToVideo"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-H-flow"
|
||||
}
|
||||
],
|
||||
"https://github.com/jcomeme/ComfyUI-AsunaroTools": [
|
||||
[
|
||||
"AsunaroAnd",
|
||||
@@ -4108,6 +4266,7 @@
|
||||
"https://github.com/jonnydolake/ComfyUI-AIR-Nodes": [
|
||||
[
|
||||
"BrightnessContrastSaturation",
|
||||
"CreateFilenameList",
|
||||
"DisplaceImageCPU",
|
||||
"DisplaceImageGPU",
|
||||
"ExtractBlackLines",
|
||||
@@ -4115,6 +4274,7 @@
|
||||
"GPUTargetLocationCrop",
|
||||
"GPUTargetLocationPaste",
|
||||
"ImageCompositeChained",
|
||||
"JoinStringLists",
|
||||
"LTXVAddGuideAIR",
|
||||
"LineDetection",
|
||||
"MangaPanelSegmentationNode",
|
||||
@@ -4181,12 +4341,9 @@
|
||||
],
|
||||
"https://github.com/kandy/ComfyUI-KAndy": [
|
||||
[
|
||||
"KAndyCivitImagesAPI",
|
||||
"KAndyCivitPromptAPI",
|
||||
"KAndyImagesByCss",
|
||||
"KAndyLoadImageFromUrl",
|
||||
"KAndyNoiseCondition",
|
||||
"KPornImageAPI",
|
||||
"KAndyTaggerModelLoader",
|
||||
"KAndyWD14Tagger",
|
||||
"KPromtGen",
|
||||
"KandySimplePrompt"
|
||||
],
|
||||
@@ -4410,6 +4567,7 @@
|
||||
[
|
||||
"LoadWanVideoClipTextEncoder",
|
||||
"LoadWanVideoT5TextEncoder",
|
||||
"ReCamMasterPoseVisualizer",
|
||||
"WanVideoBlockSwap",
|
||||
"WanVideoClipVisionEncode",
|
||||
"WanVideoContextOptions",
|
||||
@@ -4427,6 +4585,7 @@
|
||||
"WanVideoLoraBlockEdit",
|
||||
"WanVideoLoraSelect",
|
||||
"WanVideoModelLoader",
|
||||
"WanVideoReCamMasterCameraEmbed",
|
||||
"WanVideoSLG",
|
||||
"WanVideoSampler",
|
||||
"WanVideoSetBlockSwap",
|
||||
@@ -5267,20 +5426,6 @@
|
||||
"title_aux": "ComfyUI_Cluster [WIP]"
|
||||
}
|
||||
],
|
||||
"https://github.com/oshtz/ComfyUI-oshtz-nodes": [
|
||||
[
|
||||
"EasyAspectRatioNode",
|
||||
"ImageOverlayNode",
|
||||
"LLMAIONode",
|
||||
"LoRASwitcherNode",
|
||||
"LoRASwitcherNode20",
|
||||
"LoRASwitcherNode40",
|
||||
"StringSplitterNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-oshtz-nodes [WIP]"
|
||||
}
|
||||
],
|
||||
"https://github.com/osuiso-depot/comfyui-keshigom_custom": [
|
||||
[
|
||||
"KANI_Checkpoint_Loader_From_String",
|
||||
@@ -5306,6 +5451,14 @@
|
||||
"title_aux": "ComfyUI-tilefusion"
|
||||
}
|
||||
],
|
||||
"https://github.com/oxysoft/Comfy-Compel": [
|
||||
[
|
||||
"CLIPEmbedCompel"
|
||||
],
|
||||
{
|
||||
"title_aux": "Comfy-Compel"
|
||||
}
|
||||
],
|
||||
"https://github.com/oyvindg/ComfyUI-TrollSuite": [
|
||||
[
|
||||
"BinaryImageMask",
|
||||
@@ -5413,6 +5566,14 @@
|
||||
"title_aux": "ComfyUI-PixuAI"
|
||||
}
|
||||
],
|
||||
"https://github.com/pmarmotte2/Comfyui-VibeVoiceSelector": [
|
||||
[
|
||||
"VibeVoiceSelector"
|
||||
],
|
||||
{
|
||||
"title_aux": "VibeVoiceSelector [WIP]"
|
||||
}
|
||||
],
|
||||
"https://github.com/poisenbery/NudeNet-Detector-Provider": [
|
||||
[
|
||||
"NudeNetDetectorProvider"
|
||||
@@ -5773,7 +5934,8 @@
|
||||
"https://github.com/smthemex/ComfyUI_MangaNinjia": [
|
||||
[
|
||||
"MangaNinjiaLoader",
|
||||
"MangaNinjiaSampler"
|
||||
"MangaNinjiaSampler",
|
||||
"MarkImageNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_MangaNinjia [WIP]"
|
||||
@@ -5955,6 +6117,14 @@
|
||||
"title_aux": "comfyui_molook_nodes [WIP]"
|
||||
}
|
||||
],
|
||||
"https://github.com/techtruth/ComfyUI-Dreambooth": [
|
||||
[
|
||||
"DreamboothNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-Dreambooth"
|
||||
}
|
||||
],
|
||||
"https://github.com/techzuhaib/ComfyUI-CacheImageNode": [
|
||||
[
|
||||
"CacheImageNode"
|
||||
@@ -5976,9 +6146,9 @@
|
||||
[
|
||||
"CLIPTokenCounter",
|
||||
"GeminiNode",
|
||||
"Gemma3VisionNode",
|
||||
"KoboldCppApiNode",
|
||||
"KoboldCppLauncherNode"
|
||||
"KoboldCppLauncherNode",
|
||||
"LoraStrengthXYPlot"
|
||||
],
|
||||
{
|
||||
"title_aux": "Divergent Nodes [WIP]"
|
||||
@@ -5986,12 +6156,26 @@
|
||||
],
|
||||
"https://github.com/thisiseddy-ab/ComfyUI-Edins-Ultimate-Pack": [
|
||||
[
|
||||
"EUP - Adaptive Tiling Strategy Parameters",
|
||||
"EUP - Adjacency Padded Tiling Strategy Parameters",
|
||||
"EUP - Advanced Pixel TiledKSample Upscaler Provider",
|
||||
"EUP - Advanced Pixel TiledKSample Upscaler Provider Pipe",
|
||||
"EUP - Aspect Adaption Denoising Strategy Parameters",
|
||||
"EUP - Context Padded Tiling Strategy Parameters",
|
||||
"EUP - Custom Aspect Ratio",
|
||||
"EUP - Hierarchical Tiling Strategy Parameters",
|
||||
"EUP - Iterative Latent Upscaler",
|
||||
"EUP - Latent Merger",
|
||||
"EUP - Latent Tiler",
|
||||
"EUP - Non-Uniform Tiling Strategy Parameters",
|
||||
"EUP - Overlaping Tiling Strategy Parameters",
|
||||
"EUP - Padded Tiling Strategy Parameters",
|
||||
"EUP - Pixel TiledKSample Upscaler Provider",
|
||||
"EUP - Pixel TiledKSample Upscaler Provider Pipe",
|
||||
"EUP - Random Tiling Strategy Parameters",
|
||||
"EUP - Random-Hierarchical Tiling Strategy Parameters",
|
||||
"EUP - Sampler's Advanced Parameters",
|
||||
"EUP - Simple Tiling Strategy Parameters",
|
||||
"EUP - Smmooth Denoising Strategy Parameters",
|
||||
"EUP - Tiled KSampler",
|
||||
"EUP - Tiled KSampler Advanced"
|
||||
],
|
||||
@@ -6076,6 +6260,24 @@
|
||||
"title_aux": "ComfyUI-TDNodes [WIP]"
|
||||
}
|
||||
],
|
||||
"https://github.com/tzsoulcap/ComfyUI-SaveImg-W-MetaData": [
|
||||
[
|
||||
"CAP Cfg Literal",
|
||||
"CAP Checkpoint Selector",
|
||||
"CAP Int Literal",
|
||||
"CAP Load Image with Metadata",
|
||||
"CAP Sampler Selector",
|
||||
"CAP Save Image w/Metadata",
|
||||
"CAP Scheduler Selector",
|
||||
"CAP Seed Generator",
|
||||
"CAP String Literal",
|
||||
"CAP Tag Image",
|
||||
"CAP Width/Height Literal"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-SaveImg-W-MetaData"
|
||||
}
|
||||
],
|
||||
"https://github.com/umisetokikaze/comfyui_mergekit": [
|
||||
[
|
||||
"DefineSaveName",
|
||||
@@ -6154,6 +6356,7 @@
|
||||
"https://github.com/watarika/ComfyUI-Text-Utility": [
|
||||
[
|
||||
"LoadTextFile",
|
||||
"PromptsFromTextbox",
|
||||
"RemoveComments",
|
||||
"SaveTextFile",
|
||||
"StringsFromTextbox"
|
||||
@@ -6206,6 +6409,14 @@
|
||||
"title_aux": "Comfyui-zZzZz [UNSAFE]"
|
||||
}
|
||||
],
|
||||
"https://github.com/wordbrew/comfyui-wan-control-nodes": [
|
||||
[
|
||||
"WanWeightedControlToVideo"
|
||||
],
|
||||
{
|
||||
"title_aux": "WAN Control Nodes for ComfyUI [WIP]"
|
||||
}
|
||||
],
|
||||
"https://github.com/wormley/comfyui-wormley-nodes": [
|
||||
[
|
||||
"CheckpointVAELoaderSimpleText",
|
||||
@@ -6307,6 +6518,77 @@
|
||||
"title_aux": "comfyui-deepseek [WIP]"
|
||||
}
|
||||
],
|
||||
"https://github.com/yanlang0123/ComfyUI_Lam": [
|
||||
[
|
||||
"AppParams",
|
||||
"AspectRatio",
|
||||
"AutioPath",
|
||||
"DoWhileEnd",
|
||||
"DoWhileStart",
|
||||
"EasyPromptSelecto",
|
||||
"FaceFusion",
|
||||
"ForEnd",
|
||||
"ForInnerEnd",
|
||||
"ForInnerStart",
|
||||
"ForStart",
|
||||
"GLM3Prompt",
|
||||
"IdentifyingQR",
|
||||
"IfInnerExecute",
|
||||
"Image2Video",
|
||||
"ImageAddMask",
|
||||
"ImageBlank",
|
||||
"ImageClone",
|
||||
"ImageCropFaces",
|
||||
"ImageLama",
|
||||
"ImageToMasks",
|
||||
"LAM.OpenPoseEditorPlus",
|
||||
"LamCommonNames",
|
||||
"LamCommonPrint",
|
||||
"LamCommonPrintNoOutput",
|
||||
"LamFaceAnalysisModels",
|
||||
"LamGetPngInfo",
|
||||
"LamLoadImageBase64",
|
||||
"LamLoadPathImage",
|
||||
"LamLoadVideo",
|
||||
"LamSaveOnly",
|
||||
"LamSwitcherCase",
|
||||
"LoadDirImgPaths",
|
||||
"LoadReplaceImage",
|
||||
"LongTextToList",
|
||||
"MultiControlNetApply",
|
||||
"MultiGLIGENTextBoxApply",
|
||||
"MultiIPAdapterRegional",
|
||||
"MultiIntFormula",
|
||||
"MultiParamFormula",
|
||||
"MultiTextConcatenate",
|
||||
"MultiTextEncode",
|
||||
"MultiTextEncodeAdvanced",
|
||||
"MultiTextSelelct",
|
||||
"MultiTextSetArea",
|
||||
"MultiTextSetGligen",
|
||||
"MultiTextSetMask",
|
||||
"OutDoWhileEnd",
|
||||
"OutDoWhileStart",
|
||||
"PreviewImageLam",
|
||||
"PromptTranslator",
|
||||
"QRCode",
|
||||
"SaveImageLam",
|
||||
"SaveImgOutputLam",
|
||||
"SectionEnd",
|
||||
"SectionStart",
|
||||
"StyleSelecto",
|
||||
"Text2AutioEdgeTts",
|
||||
"TextListSelelct",
|
||||
"VideoAddAudio",
|
||||
"VideoFaceFusion",
|
||||
"VideoPath",
|
||||
"WaitImagSelector",
|
||||
"ZhPromptTranslator"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_Lam"
|
||||
}
|
||||
],
|
||||
"https://github.com/yichengup/Comfyui-NodeSpark": [
|
||||
[
|
||||
"ImageCircleWarp",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,15 @@
|
||||
{
|
||||
"custom_nodes": [
|
||||
{
|
||||
"author": "SanDiegoDude",
|
||||
"title": "ComfyUI-HiDream-Sampler [WIP]",
|
||||
"reference": "https://github.com/SanDiegoDude/ComfyUI-HiDream-Sampler",
|
||||
"files": [
|
||||
"https://github.com/SanDiegoDude/ComfyUI-HiDream-Sampler"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A collection of enhanced nodes for ComfyUI that provide powerful additional functionality to your workflows.\nNOTE: The files in the repo are not organized."
|
||||
},
|
||||
{
|
||||
"author": "PramaLLC",
|
||||
"title": "ComfyUI BEN - Background Erase Network",
|
||||
|
||||
@@ -10,6 +10,169 @@
|
||||
|
||||
|
||||
|
||||
{
|
||||
"author": "brantje",
|
||||
"title": "ComfyUI-api-tools",
|
||||
"id": "comfyui_api_tools",
|
||||
"reference": "https://github.com/brantje/ComfyUI-api-tools",
|
||||
"files": [
|
||||
"https://github.com/brantje/ComfyUI-api-tools"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Adds extra API functionallity and prometheus endpoint"
|
||||
},
|
||||
{
|
||||
"author": "Yuan-ManX",
|
||||
"title": "ComfyUI-UNO",
|
||||
"reference": "https://github.com/Yuan-ManX/ComfyUI-UNO",
|
||||
"files": [
|
||||
"https://github.com/Yuan-ManX/ComfyUI-UNO"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI nodes for UNO model."
|
||||
},
|
||||
{
|
||||
"author": "ImagineerNL",
|
||||
"title": "ComfyUI-IMGNR-Utils",
|
||||
"reference": "https://github.com/ImagineerNL/ComfyUI-IMGNR-Utils",
|
||||
"files": [
|
||||
"https://github.com/ImagineerNL/ComfyUI-IMGNR-Utils"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI Utility Nodes by Imagineer. Currently 1: Catch and Edit Text, useful for grabbing AI generated prompts which you edit by hand. Doing so mutes the upstream node, improving speed and saving external calls and budget."
|
||||
},
|
||||
{
|
||||
"author": "mw",
|
||||
"title": "MW-ComfyUI_PortraitTools",
|
||||
"reference": "https://github.com/billwuhao/ComfyUI_PortraitTools",
|
||||
"files": [
|
||||
"https://github.com/billwuhao/ComfyUI_PortraitTools"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Portrait Tools: Facial detection cropping, alignment, ID photo, etc."
|
||||
},
|
||||
{
|
||||
"author": "uihp",
|
||||
"title": "ComfyUI-String-Chain",
|
||||
"reference": "https://github.com/uihp/ComfyUI-String-Chain",
|
||||
"files": [
|
||||
"https://github.com/uihp/ComfyUI-String-Chain"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "String Chain: Reconnect your prompts"
|
||||
},
|
||||
{
|
||||
"author": "jerrywap",
|
||||
"title": "ComfyUI_LoadImageFromHttpURL",
|
||||
"id": "load-image-from-http-url",
|
||||
"reference": "https://github.com/jerrywap/ComfyUI_LoadImageFromHttpURL",
|
||||
"files": [
|
||||
"https://github.com/jerrywap/ComfyUI_LoadImageFromHttpURL"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A ComfyUI node that fetches an image from an HTTP URL and returns it as an image tensor. Useful for API-based workflows."
|
||||
},
|
||||
{
|
||||
"author": "lum3on",
|
||||
"title": "HiDream Sampler",
|
||||
"id": "hidream-sampler",
|
||||
"reference": "https://github.com/lum3on/comfyui_HiDream-Sampler",
|
||||
"files": [
|
||||
"https://github.com/lum3on/comfyui_HiDream-Sampler"
|
||||
],
|
||||
"install_type": "copy",
|
||||
"description": "A custom ComfyUI node for generating images using the HiDream AI model. Uses quantization for lower memory usage."
|
||||
},
|
||||
{
|
||||
"author": "HavocsCall",
|
||||
"title": "HavocsCall's Custom ComfyUI Nodes",
|
||||
"reference": "https://github.com/HavocsCall/comfyui_HavocsCall_Custom_Nodes",
|
||||
"files": [
|
||||
"https://github.com/HavocsCall/comfyui_HavocsCall_Custom_Nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "NODES: Prompt Combiner, Float/Int Selector, Sampler Config, Text Box, Int to Float/String, Int to Float/String, Clip/Conditioning/Image/Latent/Model/String/VAE Switch"
|
||||
},
|
||||
{
|
||||
"author": "danger-electrodes",
|
||||
"title": "ComfyUI_Fawfluencer_Nodes",
|
||||
"reference": "https://github.com/danger-electrodes/ComfyUI_Fawfluencer_Nodes",
|
||||
"files": [
|
||||
"https://github.com/danger-electrodes/ComfyUI_Fawfluencer_Nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A set of node for ComfyUI to create an influencer"
|
||||
},
|
||||
{
|
||||
"author": "Burgstall-labs",
|
||||
"title": "ComfyUI-BETA-Helpernodes",
|
||||
"reference": "https://github.com/Burgstall-labs/ComfyUI-BETA-Helpernodes",
|
||||
"files": [
|
||||
"hhttps://github.com/Burgstall-labs/ComfyUI-BETA-Helpernodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom utility nodes for ComfyUI, providing helpers for tasks like video frame manipulation and advanced audio saving. Part of the 'Burgstall Enabling The Awesomeness' suite."
|
||||
},
|
||||
{
|
||||
"author": "hunzmusic",
|
||||
"title": "Comfyui-CraftsMan3DWrapper",
|
||||
"reference": "https://github.com/hunzmusic/Comfyui-CraftsMan3DWrapper",
|
||||
"files": [
|
||||
"https://github.com/hunzmusic/Comfyui-CraftsMan3DWrapper"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "This custom node package provides nodes for ComfyUI to generate 3D coarse meshes from images using the CraftsMan3D model, specifically the version utilizing DoraVAE."
|
||||
},
|
||||
{
|
||||
"author": "1038lab",
|
||||
"title": "ComfyUI-MegaTTS",
|
||||
"reference": "https://github.com/1038lab/ComfyUI-MegaTTS",
|
||||
"files": [
|
||||
"https://github.com/1038lab/ComfyUI-MegaTTS"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A ComfyUI custom node based on ByteDance MegaTTS3 MegaTTS3, enabling high-quality text-to-speech synthesis with voice cloning capabilities for both Chinese and English."
|
||||
},
|
||||
{
|
||||
"author": "ShmuelRonen",
|
||||
"title": "ComfyUI-Veo2-Experimental",
|
||||
"reference": "https://github.com/ShmuelRonen/ComfyUI-Veo2-Experimental",
|
||||
"files": [
|
||||
"https://github.com/ShmuelRonen/ComfyUI-Veo2-Experimental"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A custom node extension for ComfyUI that integrates Google's Veo 2 text-to-video generation capabilities."
|
||||
},
|
||||
{
|
||||
"author": "badxprogramm",
|
||||
"title": "GradientBlurNode for ComfyUI",
|
||||
"reference": "https://github.com/badxprogramm/ComfyUI-GradientBlur",
|
||||
"files": [
|
||||
"https://github.com/badxprogramm/ComfyUI-GradientBlur"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "GradientBlurNode is a custom node for ComfyUI that allows for gradient-based image blurring. This tool provides precise control over the direction, intensity, and distribution of the blur, making it ideal for creating smooth transitions, focusing attention on specific parts of an image, or adding artistic effects."
|
||||
},
|
||||
{
|
||||
"author": "linksluckytime",
|
||||
"title": "comfyui_snacknodes",
|
||||
"reference": "https://github.com/linksluckytime/comfyui_snacknodes",
|
||||
"files": [
|
||||
"https://github.com/linksluckytime/comfyui_snacknodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A collection of custom nodes for ComfyUI"
|
||||
},
|
||||
{
|
||||
"author": "HM-RunningHub",
|
||||
"title": "ComfyUI_RH_UNO",
|
||||
"reference": "https://github.com/HM-RunningHub/ComfyUI_RH_UNO",
|
||||
"files": [
|
||||
"https://github.com/HM-RunningHub/ComfyUI_RH_UNO"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "This is a UNO ComfyUI plugin implementation that can run the full version with 24GB VRAM, as well as quickly run the FP8 version."
|
||||
},
|
||||
{
|
||||
"author": "lquesada",
|
||||
"title": "ComfyUI-Interactive",
|
||||
|
||||
@@ -67,6 +67,16 @@
|
||||
"title_aux": "ComfyUI-EdgeTTS"
|
||||
}
|
||||
],
|
||||
"https://github.com/1038lab/ComfyUI-MegaTTS": [
|
||||
[
|
||||
"MegaTTS3",
|
||||
"MegaTTS3S",
|
||||
"MegaTTS_VoiceMaker"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-MegaTTS"
|
||||
}
|
||||
],
|
||||
"https://github.com/1038lab/ComfyUI-OmniGen": [
|
||||
[
|
||||
"ailab_OmniGen"
|
||||
@@ -1577,28 +1587,10 @@
|
||||
"EXPORT (JOV) \ud83d\udcfd",
|
||||
"FILTER MASK (JOV) \ud83e\udd3f",
|
||||
"FLATTEN (JOV) \u2b07\ufe0f",
|
||||
"GLSL (JOV) \ud83c\udf69",
|
||||
"GLSL BLEND LINEAR (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL COLOR CONVERSION (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL COLOR PALETTE (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL CONICAL GRADIENT (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL DIRECTIONAL WARP (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL FILTER RANGE (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL GRAYSCALE (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL HSV ADJUST (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL INVERT (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL NORMAL (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL NORMAL BLEND (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL POSTERIZE (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GLSL TRANSFORM (JOV) \ud83e\uddd9\ud83c\udffd",
|
||||
"GRADIENT MAP (JOV) \ud83c\uddf2\ud83c\uddfa",
|
||||
"GRAPH (JOV) \ud83d\udcc8",
|
||||
"IMAGE INFO (JOV) \ud83d\udcda",
|
||||
"LERP (JOV) \ud83d\udd30",
|
||||
"MIDI FILTER (JOV) \u2733\ufe0f",
|
||||
"MIDI FILTER EZ (JOV) \u2747\ufe0f",
|
||||
"MIDI MESSAGE (JOV) \ud83c\udf9b\ufe0f",
|
||||
"MIDI READER (JOV) \ud83c\udfb9",
|
||||
"OP BINARY (JOV) \ud83c\udf1f",
|
||||
"OP UNARY (JOV) \ud83c\udfb2",
|
||||
"PIXEL MERGE (JOV) \ud83e\udec2",
|
||||
@@ -1609,12 +1601,9 @@
|
||||
"ROUTE (JOV) \ud83d\ude8c",
|
||||
"SAVE OUTPUT (JOV) \ud83d\udcbe",
|
||||
"SHAPE GEN (JOV) \u2728",
|
||||
"SPOUT WRITER (JOV) \ud83c\udfa5",
|
||||
"STACK (JOV) \u2795",
|
||||
"STEREOGRAM (JOV) \ud83d\udcfb",
|
||||
"STEREOSCOPIC (JOV) \ud83d\udd76\ufe0f",
|
||||
"STREAM READER (JOV) \ud83d\udcfa",
|
||||
"STREAM WRITER (JOV) \ud83c\udf9e\ufe0f",
|
||||
"STRINGER (JOV) \ud83e\ude80",
|
||||
"SWIZZLE (JOV) \ud83d\ude35",
|
||||
"TEXT GEN (JOV) \ud83d\udcdd",
|
||||
@@ -2396,7 +2385,8 @@
|
||||
"https://github.com/Burgstall-labs/ComfyUI-BETA-Cropnodes": [
|
||||
[
|
||||
"BETACrop",
|
||||
"BETAStitch"
|
||||
"BETAStitch",
|
||||
"SaveAudioAdvanced_BETA"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-BETA-Cropnodes"
|
||||
@@ -2658,6 +2648,7 @@
|
||||
"CLIPTextEncodeFluxUnguided",
|
||||
"ClownRegionalConditioning",
|
||||
"ClownRegionalConditioning3",
|
||||
"ClownRegionalConditioning_AB",
|
||||
"ClownScheduler",
|
||||
"ClownpileModelWanVideo",
|
||||
"Conditioning Recast FP64",
|
||||
@@ -2777,6 +2768,7 @@
|
||||
"Tan Scheduler 2",
|
||||
"Tan Scheduler 2 Simple",
|
||||
"TemporalMaskGenerator",
|
||||
"TemporalSplitAttnMask",
|
||||
"TextBox1",
|
||||
"TextBox2",
|
||||
"TextBox3",
|
||||
@@ -2993,6 +2985,7 @@
|
||||
"DynamicVAESwitch",
|
||||
"EvaluaterNode",
|
||||
"Modelswitch",
|
||||
"PeopleEvaluationNode",
|
||||
"SanitizeFilename",
|
||||
"SystemPromp",
|
||||
"Textswitch",
|
||||
@@ -4635,6 +4628,15 @@
|
||||
"title_aux": "ComfyUI_RH_OminiControl"
|
||||
}
|
||||
],
|
||||
"https://github.com/HM-RunningHub/ComfyUI_RH_UNO": [
|
||||
[
|
||||
"RunningHub_UNO_Loadmodel",
|
||||
"RunningHub_UNO_Sampler"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_RH_UNO"
|
||||
}
|
||||
],
|
||||
"https://github.com/Haiper-ai/ComfyUI-HaiperAI-API": [
|
||||
[
|
||||
"HaiperImage2Video",
|
||||
@@ -4719,6 +4721,29 @@
|
||||
"title_aux": "ComfyUI ReSharpen"
|
||||
}
|
||||
],
|
||||
"https://github.com/HavocsCall/comfyui_HavocsCall_Custom_Nodes": [
|
||||
[
|
||||
"Clip Switch",
|
||||
"Conditioning Switch",
|
||||
"Float Selector",
|
||||
"Float to Int",
|
||||
"Float to String",
|
||||
"Image Switch",
|
||||
"Int Selector",
|
||||
"Int to Float",
|
||||
"Int to String",
|
||||
"Latent Switch",
|
||||
"Model Switch",
|
||||
"Prompt Combiner",
|
||||
"Sampler Config",
|
||||
"String Switch",
|
||||
"Text Box",
|
||||
"VAE Switch"
|
||||
],
|
||||
{
|
||||
"title_aux": "HavocsCall's Custom ComfyUI Nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/HaydenReeve/ComfyUI-Better-Strings": [
|
||||
[
|
||||
"BetterString"
|
||||
@@ -4944,6 +4969,14 @@
|
||||
"title_aux": "Simple String Repository"
|
||||
}
|
||||
],
|
||||
"https://github.com/ImagineerNL/ComfyUI-IMGNR-Utils": [
|
||||
[
|
||||
"CatchEditTextNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-IMGNR-Utils"
|
||||
}
|
||||
],
|
||||
"https://github.com/ImagineerNL/ComfyUI-ToSVG-Potracer": [
|
||||
[
|
||||
"PotracerVectorize"
|
||||
@@ -5497,8 +5530,15 @@
|
||||
"https://github.com/Jokimbe/ComfyUI-DrawThings-gRPC": [
|
||||
[
|
||||
"DrawThingsControlNet",
|
||||
"DrawThingsHighResFix",
|
||||
"DrawThingsLoRA",
|
||||
"DrawThingsSampler"
|
||||
"DrawThingsNegative",
|
||||
"DrawThingsPositive",
|
||||
"DrawThingsRefiner",
|
||||
"DrawThingsSampler",
|
||||
"DrawThingsTeaCache",
|
||||
"DrawThingsUpscaler",
|
||||
"DrawThingsVideo"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-DrawThings-gRPC"
|
||||
@@ -6934,6 +6974,7 @@
|
||||
[
|
||||
"iToolsAddOverlay",
|
||||
"iToolsCheckerBoard",
|
||||
"iToolsCompareImage",
|
||||
"iToolsGridFiller",
|
||||
"iToolsKSampler",
|
||||
"iToolsLineLoader",
|
||||
@@ -7987,6 +8028,7 @@
|
||||
"FormatConcatStrings",
|
||||
"FormattingSingle",
|
||||
"FourierAnalysisNode",
|
||||
"ImageDifference",
|
||||
"MosaicEffectNode",
|
||||
"PWLoraNameCollector",
|
||||
"PWLoraSelector",
|
||||
@@ -8993,15 +9035,9 @@
|
||||
],
|
||||
"https://github.com/Shiba-2-shiba/comfyui-color-ascii-art-node": [
|
||||
[
|
||||
"ASCIIArtNode",
|
||||
"ASCIIArtNodev2",
|
||||
"ASCIIArtSinglefontNode"
|
||||
"ASCIIArtNodeV3"
|
||||
],
|
||||
{
|
||||
"author": "Shiba-2-shiba",
|
||||
"description": "This node generates colorful ASCII art using custom character sets and fonts.",
|
||||
"nickname": "ColorASCII",
|
||||
"title": "Colorful ASCII Art Node",
|
||||
"title_aux": "ComfyUI-color-ascii-art-node"
|
||||
}
|
||||
],
|
||||
@@ -9172,6 +9208,16 @@
|
||||
"title_aux": "ComfyUI-SVDResizer"
|
||||
}
|
||||
],
|
||||
"https://github.com/ShmuelRonen/ComfyUI-Veo2-Experimental": [
|
||||
[
|
||||
"VeoTextToVideo",
|
||||
"VeoToVHS",
|
||||
"VeoVideoPreview"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-Veo2-Experimental"
|
||||
}
|
||||
],
|
||||
"https://github.com/ShmuelRonen/ComfyUI-WanVideoKsampler": [
|
||||
[
|
||||
"WanVideoKsampler"
|
||||
@@ -9589,6 +9635,7 @@
|
||||
"SDVN AnyDownload List",
|
||||
"SDVN Apply Style Model",
|
||||
"SDVN Auto Generate",
|
||||
"SDVN AutoSwitch",
|
||||
"SDVN Boolean",
|
||||
"SDVN CLIP Download",
|
||||
"SDVN CLIP Text Encode",
|
||||
@@ -9634,6 +9681,7 @@
|
||||
"SDVN Load Lora",
|
||||
"SDVN Load Model",
|
||||
"SDVN Load Text",
|
||||
"SDVN LoadPinterest",
|
||||
"SDVN Logic",
|
||||
"SDVN Loop Inpaint Stitch",
|
||||
"SDVN Lora Download",
|
||||
@@ -11603,6 +11651,19 @@
|
||||
"title_aux": "ComfyUI-StyleStudio"
|
||||
}
|
||||
],
|
||||
"https://github.com/Yuan-ManX/ComfyUI-UNO": [
|
||||
[
|
||||
"ConfigSave",
|
||||
"ImageConcat",
|
||||
"ImagePathLoader",
|
||||
"ImageSave",
|
||||
"UNOGenerator",
|
||||
"UNOParams"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-UNO"
|
||||
}
|
||||
],
|
||||
"https://github.com/ZHO-ZHO-ZHO/ComfyUI-APISR": [
|
||||
[
|
||||
"APISR_Lterative_Zho",
|
||||
@@ -11997,7 +12058,8 @@
|
||||
"Rotate Module (Bending)",
|
||||
"Scale Module (Bending)",
|
||||
"Sobel Module (Bending)",
|
||||
"Threshold Module (Bending)"
|
||||
"Threshold Module (Bending)",
|
||||
"Visualize Feature Map"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI Model Bending"
|
||||
@@ -12322,6 +12384,7 @@
|
||||
"CogVideoXFunInpaintSampler",
|
||||
"CogVideoXFunT2VSampler",
|
||||
"CogVideoXFunV2VSampler",
|
||||
"FunRiflex",
|
||||
"FunTextBox",
|
||||
"LoadCogVideoXFunLora",
|
||||
"LoadCogVideoXFunModel",
|
||||
@@ -13202,6 +13265,14 @@
|
||||
"title_aux": "LoRA Tag Loader for ComfyUI"
|
||||
}
|
||||
],
|
||||
"https://github.com/badxprogramm/ComfyUI-GradientBlur": [
|
||||
[
|
||||
"GradientBlur"
|
||||
],
|
||||
{
|
||||
"title_aux": "GradientBlurNode for ComfyUI"
|
||||
}
|
||||
],
|
||||
"https://github.com/baicai99/ComfyUI-FrameSkipping": [
|
||||
[
|
||||
"FrameSelector",
|
||||
@@ -13562,7 +13633,7 @@
|
||||
"MultiLinePrompt"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_DiffRhythm"
|
||||
"title_aux": "ComfyUI_DiffRhythm_MW"
|
||||
}
|
||||
],
|
||||
"https://github.com/billwuhao/ComfyUI_EraX-WoW-Turbo": [
|
||||
@@ -13607,7 +13678,19 @@
|
||||
"LoadPrompt"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_OneButtonPrompt"
|
||||
"title_aux": "MW-ComfyUI_OneButtonPrompt"
|
||||
}
|
||||
],
|
||||
"https://github.com/billwuhao/ComfyUI_PortraitTools": [
|
||||
[
|
||||
"AlignFace",
|
||||
"BeautifyPhoto",
|
||||
"DetectCropFace",
|
||||
"IDPhotos",
|
||||
"RMBG"
|
||||
],
|
||||
{
|
||||
"title_aux": "MW-ComfyUI_PortraitTools"
|
||||
}
|
||||
],
|
||||
"https://github.com/billwuhao/ComfyUI_SparkTTS": [
|
||||
@@ -14008,6 +14091,14 @@
|
||||
"title_aux": "braintacles-nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/brantje/ComfyUI-api-tools": [
|
||||
[
|
||||
"SimpleGenImageInterface"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-api-tools"
|
||||
}
|
||||
],
|
||||
"https://github.com/brayevalerien/ComfyUI-resynthesizer": [
|
||||
[
|
||||
"Resynthesize"
|
||||
@@ -16320,6 +16411,7 @@
|
||||
"VPScheduler",
|
||||
"VideoLinearCFGGuidance",
|
||||
"VideoTriangleCFGGuidance",
|
||||
"VoxelToMesh",
|
||||
"VoxelToMeshBasic",
|
||||
"WanFunControlToVideo",
|
||||
"WanFunInpaintToVideo",
|
||||
@@ -16906,6 +16998,54 @@
|
||||
"title_aux": "SDXL Auto Prompter"
|
||||
}
|
||||
],
|
||||
"https://github.com/danger-electrodes/ComfyUI_Fawfluencer_Nodes": [
|
||||
[
|
||||
"FawfaceModelSpreadsheetRealismNode",
|
||||
"FawfakeAuthenticImageSaveNode",
|
||||
"FawfluxencerNode",
|
||||
"FawfulizedAddImagesToImageList",
|
||||
"FawfulizedEmptyImageList",
|
||||
"FawfulizedHunyuanAddNoise",
|
||||
"FawfulizedHunyuanBasicGuider",
|
||||
"FawfulizedHunyuanBasicScheduler",
|
||||
"FawfulizedHunyuanBetaSamplingScheduler",
|
||||
"FawfulizedHunyuanCFGGuider",
|
||||
"FawfulizedHunyuanControlNetApply",
|
||||
"FawfulizedHunyuanControlNetApplyAdvanced",
|
||||
"FawfulizedHunyuanControlNetLoader",
|
||||
"FawfulizedHunyuanDiffControlNetLoader",
|
||||
"FawfulizedHunyuanDisableNoise",
|
||||
"FawfulizedHunyuanDualCFGGuider",
|
||||
"FawfulizedHunyuanExponentialScheduler",
|
||||
"FawfulizedHunyuanFlipSigmas",
|
||||
"FawfulizedHunyuanKSamplerSelect",
|
||||
"FawfulizedHunyuanKarrasScheduler",
|
||||
"FawfulizedHunyuanLaplaceScheduler",
|
||||
"FawfulizedHunyuanLatentVideo",
|
||||
"FawfulizedHunyuanPolyexponentialScheduler",
|
||||
"FawfulizedHunyuanRandomNoise",
|
||||
"FawfulizedHunyuanSDTurboScheduler",
|
||||
"FawfulizedHunyuanSamplerCustom",
|
||||
"FawfulizedHunyuanSamplerCustomAdvanced",
|
||||
"FawfulizedHunyuanSamplerDPMAdaptative",
|
||||
"FawfulizedHunyuanSamplerDPMPP_2M_SDE",
|
||||
"FawfulizedHunyuanSamplerDPMPP_2S_Ancestral",
|
||||
"FawfulizedHunyuanSamplerDPMPP_3M_SDE",
|
||||
"FawfulizedHunyuanSamplerDPMPP_SDE",
|
||||
"FawfulizedHunyuanSamplerEulerAncestral",
|
||||
"FawfulizedHunyuanSamplerEulerAncestralCFGPP",
|
||||
"FawfulizedHunyuanSamplerLMS",
|
||||
"FawfulizedHunyuanSetFirstSigma",
|
||||
"FawfulizedHunyuanSetLatentNoiseMask",
|
||||
"FawfulizedHunyuanSplitSigmas",
|
||||
"FawfulizedHunyuanSplitSigmasDenoise",
|
||||
"FawfulizedHunyuanVPScheduler",
|
||||
"Img2ImgFawfluencerNodeSDXL"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_Fawfluencer_Nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/daniabib/ComfyUI_ProPainter_Nodes": [
|
||||
[
|
||||
"ProPainterInpaint",
|
||||
@@ -17678,7 +17818,7 @@
|
||||
"title_aux": "Semantic-SAM"
|
||||
}
|
||||
],
|
||||
"https://github.com/edelvarden/ComfyUI-ImageMetadataExtension": [
|
||||
"https://github.com/edelvarden/comfyui_image_metadata_extension": [
|
||||
[
|
||||
"CreateExtraMetaData",
|
||||
"SaveImageWithMetaData"
|
||||
@@ -18280,6 +18420,7 @@
|
||||
"FL_NodeLoader",
|
||||
"FL_NodePackLoader",
|
||||
"FL_OllamaCaptioner",
|
||||
"FL_PDFEncryptor",
|
||||
"FL_PDFImageExtractor",
|
||||
"FL_PDFLoader",
|
||||
"FL_PDFMerger",
|
||||
@@ -18290,6 +18431,7 @@
|
||||
"FL_PaperDrawn",
|
||||
"FL_PasteOnCanvas",
|
||||
"FL_PathTypeChecker",
|
||||
"FL_PixVerseAPI",
|
||||
"FL_PixelArtShader",
|
||||
"FL_PixelSort",
|
||||
"FL_ProResVideo",
|
||||
@@ -18311,6 +18453,7 @@
|
||||
"FL_SimpleGPTVision",
|
||||
"FL_SystemCheck",
|
||||
"FL_TetrisGame",
|
||||
"FL_TextToPDF",
|
||||
"FL_TimeLine",
|
||||
"FL_UpscaleModel",
|
||||
"FL_VideoCaptionSaver",
|
||||
@@ -18857,6 +19000,7 @@
|
||||
"ImgTextSwitch",
|
||||
"Load Remote Models",
|
||||
"LoadText|plush",
|
||||
"Model-CLIP Output Switch",
|
||||
"ParseJSON",
|
||||
"Plush-Exif Wrangler",
|
||||
"Random Image Output",
|
||||
@@ -20019,17 +20163,6 @@
|
||||
"title_aux": "ComfyUI-Select-Any"
|
||||
}
|
||||
],
|
||||
"https://github.com/hylarucoder/comfyui-copilot": [
|
||||
[
|
||||
"EagleImageNode",
|
||||
"SDXLPromptStyler",
|
||||
"SDXLPromptStylerAdvanced",
|
||||
"SDXLResolutionPresets"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-copilot"
|
||||
}
|
||||
],
|
||||
"https://github.com/hyunamy/comfy-ui-on-complete-email-me": [
|
||||
[
|
||||
"OnCompleteEmailMe",
|
||||
@@ -20240,12 +20373,17 @@
|
||||
"title_aux": "IF_AI_LoadImages"
|
||||
}
|
||||
],
|
||||
"https://github.com/ifmylove2011/comfyui-missing-tool": [
|
||||
"https://github.com/ifmylove2011/comfyui-missed-tool": [
|
||||
[
|
||||
"ImageQueueLoader",
|
||||
"LoadImageA",
|
||||
"LoraLoad",
|
||||
"LoraMerge",
|
||||
"LoraSaver",
|
||||
"ScaleMultilplePixels",
|
||||
"TrimBG",
|
||||
"TrimBGAdvanced"
|
||||
"TrimBGAdvanced",
|
||||
"TxtSave"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-missing-tool"
|
||||
@@ -20256,7 +20394,10 @@
|
||||
"Light-Tool: AddBackground",
|
||||
"Light-Tool: AddBackgroundV2",
|
||||
"Light-Tool: BoundingBoxCropping",
|
||||
"Light-Tool: Calculate",
|
||||
"Light-Tool: DeserializeJsonString",
|
||||
"Light-Tool: GetImageSize",
|
||||
"Light-Tool: GetImagesCount",
|
||||
"Light-Tool: Hex2Rgb",
|
||||
"Light-Tool: ImageConcat",
|
||||
"Light-Tool: ImageMaskApply",
|
||||
@@ -20270,6 +20411,7 @@
|
||||
"Light-Tool: LoadImage",
|
||||
"Light-Tool: LoadImageFromURL",
|
||||
"Light-Tool: LoadImagesFromDir",
|
||||
"Light-Tool: LoadMetadataFromURL",
|
||||
"Light-Tool: LoadVideo",
|
||||
"Light-Tool: MaskBoundingBoxCropping",
|
||||
"Light-Tool: MaskContourExtractor",
|
||||
@@ -20281,9 +20423,11 @@
|
||||
"Light-Tool: RGB2RGBA",
|
||||
"Light-Tool: RGBA2RGB",
|
||||
"Light-Tool: ResizeImage",
|
||||
"Light-Tool: SaveMetadata",
|
||||
"Light-Tool: SaveToAliyunOSS",
|
||||
"Light-Tool: SaveVideo",
|
||||
"Light-Tool: ScaleImage",
|
||||
"Light-Tool: SerializeJsonObject",
|
||||
"Light-Tool: ShowText",
|
||||
"Light-Tool: SimpleImageOverlay",
|
||||
"Light-Tool: SimpleTextConnect",
|
||||
@@ -20967,7 +21111,8 @@
|
||||
"EasyControlGenerate",
|
||||
"EasyControlLoadFlux",
|
||||
"EasyControlLoadLora",
|
||||
"EasyControlLoadMultiLora"
|
||||
"EasyControlLoadMultiLora",
|
||||
"EasyControlLoadStyleLora"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-easycontrol"
|
||||
@@ -21042,6 +21187,14 @@
|
||||
"title_aux": "ComfyUI-My-Mask"
|
||||
}
|
||||
],
|
||||
"https://github.com/jerrywap/ComfyUI_LoadImageFromHttpURL": [
|
||||
[
|
||||
"LoadImageFromHttpURL"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_LoadImageFromHttpURL"
|
||||
}
|
||||
],
|
||||
"https://github.com/jerrywap/ComfyUI_UploadToWebhookHTTP": [
|
||||
[
|
||||
"UploadToWebHookHTTP"
|
||||
@@ -21293,7 +21446,13 @@
|
||||
"https://github.com/joeriben/ai4artsed_comfyui": [
|
||||
[
|
||||
"ai4artsed_ollama",
|
||||
"ai4artsed_openrouter"
|
||||
"ai4artsed_ollama_imageanalysis",
|
||||
"ai4artsed_openrouter",
|
||||
"ai4artsed_openrouter_imageanalysis",
|
||||
"ai4artsed_random_artform_generator",
|
||||
"ai4artsed_random_instruction_generator",
|
||||
"ai4artsed_random_language_selector",
|
||||
"ai4artsed_text_remix"
|
||||
],
|
||||
{
|
||||
"title_aux": "AI4ArtsEd Ollama Prompt Node"
|
||||
@@ -23278,6 +23437,14 @@
|
||||
"title_aux": "comfyui_kj"
|
||||
}
|
||||
],
|
||||
"https://github.com/linksluckytime/comfyui_snacknodes": [
|
||||
[
|
||||
"SnackImageScaler"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui_snacknodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/linshier/comfyui-remote-tools": [
|
||||
[
|
||||
"LoadBase64(js)",
|
||||
@@ -25196,6 +25363,7 @@
|
||||
"CanvasCreatorAdvanced",
|
||||
"CanvasCreatorBasic",
|
||||
"CanvasCreatorSimple",
|
||||
"CheckpointLoaderSimpleMira",
|
||||
"CreateMaskWithCanvas",
|
||||
"CreateNestedPNGMask",
|
||||
"CreateSimpleMask",
|
||||
@@ -25221,6 +25389,7 @@
|
||||
"ImageHUE",
|
||||
"ImageRGBChannel",
|
||||
"ImageSaturation",
|
||||
"ImageSaverMira",
|
||||
"ImageSharpness",
|
||||
"ImageToneCurve",
|
||||
"IntMultiplication",
|
||||
@@ -25847,6 +26016,7 @@
|
||||
[
|
||||
"Nilor Categorize String",
|
||||
"Nilor Count Images In Directory",
|
||||
"Nilor Extract Filename from Path",
|
||||
"Nilor Int To List Of Bools",
|
||||
"Nilor Interpolated Float List",
|
||||
"Nilor Inverse Map Float List",
|
||||
@@ -26010,6 +26180,7 @@
|
||||
"https://github.com/nofunstudio/Node_Fun_ComfyUI": [
|
||||
[
|
||||
"DynamicQueueCounter",
|
||||
"Fun KSampler",
|
||||
"IframeView",
|
||||
"IndexedStringSelector",
|
||||
"LayeredInfiniteZoom",
|
||||
@@ -26312,6 +26483,19 @@
|
||||
"title_aux": "ComfyUI-wanBlockswap"
|
||||
}
|
||||
],
|
||||
"https://github.com/oshtz/ComfyUI-oshtz-nodes": [
|
||||
[
|
||||
"EasyAspectRatioNode",
|
||||
"LLMAIONode",
|
||||
"LoRASwitcherNode",
|
||||
"LoRASwitcherNode20",
|
||||
"LoRASwitcherNode40",
|
||||
"StringSplitterNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "oshtz Nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/osi1880vr/prompt_quill_comfyui": [
|
||||
[
|
||||
"PromptQuillGenerate",
|
||||
@@ -26980,6 +27164,7 @@
|
||||
],
|
||||
"https://github.com/rainlizard/ComfyUI-Raffle": [
|
||||
[
|
||||
"PreviewHistory",
|
||||
"Raffle"
|
||||
],
|
||||
{
|
||||
@@ -28373,7 +28558,6 @@
|
||||
"BizyAirSiliconCloudLLMAPI",
|
||||
"BizyAirSiliconCloudVLMAPI",
|
||||
"BizyAirTilePreprocessor",
|
||||
"BizyAirToggleServerEndpoint",
|
||||
"BizyAirUniFormer_SemSegPreprocessor",
|
||||
"BizyAirZoe_DepthMapPreprocessor",
|
||||
"BizyAir_MinusZoneChatGLM3TextEncode",
|
||||
@@ -30165,6 +30349,17 @@
|
||||
"title_aux": "comfyui-webcam-node"
|
||||
}
|
||||
],
|
||||
"https://github.com/uihp/ComfyUI-String-Chain": [
|
||||
[
|
||||
"String Chain",
|
||||
"String Concat",
|
||||
"String Toggle",
|
||||
"String Toggle (Multiline)"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-String-Chain"
|
||||
}
|
||||
],
|
||||
"https://github.com/umiyuki/comfyui-pad-to-eight": [
|
||||
[
|
||||
"Pad To Eight"
|
||||
@@ -30736,7 +30931,8 @@
|
||||
"Text_Match",
|
||||
"Whitening_Node",
|
||||
"YOLOWorld_Match",
|
||||
"YOLO_Crop"
|
||||
"YOLO_Crop",
|
||||
"YOLO_Multi_Crop"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_KimNodes"
|
||||
@@ -31282,6 +31478,7 @@
|
||||
"ImageRotate",
|
||||
"ImageSelector",
|
||||
"ImageUpscaleTiled",
|
||||
"LoadImagesFromFolder",
|
||||
"MaskBatchComposite",
|
||||
"MaskBatchCopy",
|
||||
"MaskContourFillNode",
|
||||
@@ -31295,7 +31492,8 @@
|
||||
"MaskTopNFilter",
|
||||
"TextBeforeKeyword",
|
||||
"YC Extract Number",
|
||||
"YC Text Index Switch"
|
||||
"YC Text Index Switch",
|
||||
"YC_Image_Save"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-YCNodes"
|
||||
@@ -31767,6 +31965,7 @@
|
||||
"https://github.com/yushan777/ComfyUI-Y7Nodes": [
|
||||
[
|
||||
"Y7Nodes_CLIP_TokenCounter",
|
||||
"Y7Nodes_CatchEditTextNodeDual",
|
||||
"Y7Nodes_Grid2Batch",
|
||||
"Y7Nodes_PromptEnhancerFlux",
|
||||
"Y7Nodes_ShowAnything",
|
||||
|
||||
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
|
||||
[project]
|
||||
name = "comfyui-manager"
|
||||
license = { text = "GPL-3.0-only" }
|
||||
version = "4.0"
|
||||
version = "4.0.0-beta.1"
|
||||
requires-python = ">= 3.9"
|
||||
description = "ComfyUI-Manager provides features to install and manage custom nodes for ComfyUI, as well as various functionalities to assist with ComfyUI."
|
||||
readme = "README.md"
|
||||
@@ -25,16 +25,16 @@ classifiers = [
|
||||
]
|
||||
|
||||
dependencies = [
|
||||
"GitPython",
|
||||
"PyGithub",
|
||||
"matrix-client==0.4.0",
|
||||
"transformers",
|
||||
"huggingface-hub>0.20",
|
||||
"typer",
|
||||
"rich",
|
||||
"typing-extensions",
|
||||
"toml",
|
||||
"uv",
|
||||
"GitPython",
|
||||
"PyGithub",
|
||||
"matrix-client==0.4.0",
|
||||
"transformers",
|
||||
"huggingface-hub>0.20",
|
||||
"typer",
|
||||
"rich",
|
||||
"typing-extensions",
|
||||
"toml",
|
||||
"uv",
|
||||
"chardet"
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user