Compare commits

..

5 Commits

Author SHA1 Message Date
dr.lt.data 54025767c7 Merge branch 'main' into feat/component-manager 9 months ago
dr.lt.data 45db3eed1c Merge branch 'main' into feat/component-manager 9 months ago
Dr.Lt.Data 3fe4aea38a wip 10 months ago
Dr.Lt.Data b4a2c52d39 Merge branch 'main' into feat/component-manager 10 months ago
Dr.Lt.Data 998e211ad4 wip 10 months ago
  1. 2
      .gitignore
  2. 100
      README.md
  3. 2412
      __init__.py
  4. 15
      alter-list.json
  5. 21
      check.bat
  6. 1
      check.sh
  7. 1018
      cm-cli.py
  8. 4530
      custom-node-list.json
  9. 146
      docs/en/cm-cli.md
  10. 149
      docs/ko/cm-cli.md
  11. 5523
      extension-node-map.json
  12. 155
      git_helper.py
  13. 3354
      github-stats.json
  14. 1200
      glob/manager_core.py
  15. 1679
      glob/manager_server.py
  16. 63
      glob/manager_util.py
  17. 2
      js/a1111-alter-downloader.js
  18. 11
      js/cm-api.js
  19. 116
      js/comfyui-manager.js
  20. 33
      js/comfyui-share-common.js
  21. 4
      js/comfyui-share-openart.js
  22. 77
      js/common.js
  23. 839
      js/component-builder.js
  24. 1087
      js/components-manager.js
  25. 320
      js/custom-nodes-downloader.js
  26. 5
      js/model-downloader.js
  27. 32
      js/snapshot.js
  28. 819
      model-list.json
  29. 656
      node_db/dev/custom-node-list.json
  30. 537
      node_db/dev/extension-node-map.json
  31. 350
      node_db/dev/github-stats.json
  32. 40
      node_db/forked/custom-node-list.json
  33. 172
      node_db/legacy/custom-node-list.json
  34. 729
      node_db/new/custom-node-list.json
  35. 5523
      node_db/new/extension-node-map.json
  36. 968
      node_db/new/model-list.json
  37. 90
      node_db/tutorial/custom-node-list.json
  38. 28
      notebooks/comfyui_colab_with_manager.ipynb
  39. 21
      pip_overrides.json.template
  40. 203
      prestartup_script.py
  41. 6
      requirements.txt
  42. 2
      scan.sh
  43. 216
      scanner.py
  44. 2
      scripts/install-comfyui-venv-linux.sh
  45. 17
      scripts/install-comfyui-venv-win.bat

2
.gitignore vendored

@ -11,5 +11,3 @@ startup-scripts/**
matrix_auth matrix_auth
channels.list channels.list
comfyworkflows_sharekey comfyworkflows_sharekey
github-stats-cache.json
pip_overrides.json

100
README.md

@ -5,10 +5,10 @@
![menu](misc/menu.jpg) ![menu](misc/menu.jpg)
## NOTICE ## NOTICE
* V2.33 Security policy is applied. * 🏆 Join us for the [ComfyUI Workflow Contest](https://contest.openart.ai/), hosted by OpenArt AI (11.27.2023 - 12.15.2023). Our esteemed judge panel includes Scott E. Detweiler, Olivio Sarikas, MERJIC麦橘, among others. We're also thrilled to have the authors of ComfyUI Manager and AnimateDiff as our special guests!
* V2.21 [cm-cli](docs/en/cm-cli.md) tool is added. * If you wish to hide the "Share" button, click "Manager" and choose "Share: None" option.
* V2.18 to V2.18.3 is not functioning due to a severe bug. Users on these versions are advised to promptly update to V2.18.4. Please navigate to the `ComfyUI/custom_nodes/ComfyUI-Manager` directory and execute `git pull` to update.
* You can see whole nodes info on [ComfyUI Nodes Info](https://ltdrdata.github.io/) page. * You can see whole nodes info on [ComfyUI Nodes Info](https://ltdrdata.github.io/) page.
* Versions prior to V0.22.2 will no longer detect missing nodes unless using a local database. Please update ComfyUI-Manager to the latest version.
## Installation ## Installation
@ -32,32 +32,10 @@ To install ComfyUI-Manager in addition to an existing installation of ComfyUI, y
![portable-install](misc/portable-install.png) ![portable-install](misc/portable-install.png)
### Installation[method3] (Installation through comfy-cli: install ComfyUI and ComfyUI-Manager at once.) ### Installation[method3] (Installation for linux+venv: ComfyUI + ComfyUI-Manager)
> RECOMMENDED: comfy-cli provides various features to manage ComfyUI from the CLI.
* **prerequisite: python 3, git**
Windows:
```commandline
python -m venv venv
venv\Scripts\activate
pip install comfy-cli
comfy install
```
Linux/OSX:
```commandline
python -m venv venv
. venv/bin/activate
pip install comfy-cli
comfy install
```
### Installation[method4] (Installation for linux+venv: ComfyUI + ComfyUI-Manager)
To install ComfyUI with ComfyUI-Manager on Linux using a venv environment, you can follow these steps: To install ComfyUI with ComfyUI-Manager on Linux using a venv environment, you can follow these steps:
* **prerequisite: python-is-python3, python3-venv, git** prerequisite: python-is-python3, python3-venv
1. Download [scripts/install-comfyui-venv-linux.sh](https://github.com/ltdrdata/ComfyUI-Manager/raw/main/scripts/install-comfyui-venv-linux.sh) into empty install directory 1. Download [scripts/install-comfyui-venv-linux.sh](https://github.com/ltdrdata/ComfyUI-Manager/raw/main/scripts/install-comfyui-venv-linux.sh) into empty install directory
- ComfyUI will be installed in the subdirectory of the specified directory, and the directory will contain the generated executable script. - ComfyUI will be installed in the subdirectory of the specified directory, and the directory will contain the generated executable script.
@ -85,7 +63,6 @@ This repository provides Colab notebooks that allow you to install and use Comfy
* Support for automatically installing dependencies of custom nodes upon restarting Colab notebooks. * Support for automatically installing dependencies of custom nodes upon restarting Colab notebooks.
## Changes ## Changes
* **2.21** [cm-cli](docs/en/cm-cli.md) tool is added.
* **2.4** Copy the connections of the nearest node by double-clicking. * **2.4** Copy the connections of the nearest node by double-clicking.
* **2.2.3** Support Components System * **2.2.3** Support Components System
* **0.29** Add `Update all` feature * **0.29** Add `Update all` feature
@ -176,15 +153,9 @@ This repository provides Colab notebooks that allow you to install and use Comfy
* Press the "Restore" button to revert to the installation status of the respective snapshot. * Press the "Restore" button to revert to the installation status of the respective snapshot.
* However, for custom nodes not managed by Git, snapshot support is incomplete. * However, for custom nodes not managed by Git, snapshot support is incomplete.
* When you press `Restore`, it will take effect on the next ComfyUI startup. * When you press `Restore`, it will take effect on the next ComfyUI startup.
* The selected snapshot file is saved in `ComfyUI-Manager/startup-scripts/restore-snapshot.json`, and upon restarting ComfyUI, the snapshot is applied and then deleted.
![model-install-dialog](misc/snapshot.jpg)
## cm-cli: command line tools for power user ![model-install-dialog](misc/snapshot.jpg)
* A tool is provided that allows you to use the features of ComfyUI-Manager without running ComfyUI.
* For more details, please refer to the [cm-cli documentation](docs/en/cm-cli.md).
## How to register your custom node into ComfyUI-Manager ## How to register your custom node into ComfyUI-Manager
@ -192,7 +163,6 @@ This repository provides Colab notebooks that allow you to install and use Comfy
* NOTE: Before submitting the PR after making changes, please check `Use local DB` and ensure that the extension list loads without any issues in the `Install custom nodes` dialog. Occasionally, missing or extra commas can lead to JSON syntax errors. * NOTE: Before submitting the PR after making changes, please check `Use local DB` and ensure that the extension list loads without any issues in the `Install custom nodes` dialog. Occasionally, missing or extra commas can lead to JSON syntax errors.
* The remaining JSON will be updated through scripts in the future, so you don't need to worry about it. * The remaining JSON will be updated through scripts in the future, so you don't need to worry about it.
## Custom node support guide ## Custom node support guide
* Currently, the system operates by cloning the git repository and sequentially installing the dependencies listed in requirements.txt using pip, followed by invoking the install.py script. In the future, we plan to discuss and determine the specifications for supporting custom nodes. * Currently, the system operates by cloning the git repository and sequentially installing the dependencies listed in requirements.txt using pip, followed by invoking the install.py script. In the future, we plan to discuss and determine the specifications for supporting custom nodes.
@ -302,33 +272,6 @@ NODE_CLASS_MAPPINGS.update({
* `Possible(left) + Copy(right)`: When you Double-Click on the left half of the title, it operates as `Possible Input Connections`, and when you Double-Click on the right half, it operates as `Copy All Connections`. * `Possible(left) + Copy(right)`: When you Double-Click on the left half of the title, it operates as `Possible Input Connections`, and when you Double-Click on the right half, it operates as `Copy All Connections`.
* Prevent downgrade of specific packages
* List the package names in the `downgrade_blacklist` section of the `config.ini` file, separating them with commas.
* e.g
```
downgrade_blacklist = diffusers, kornia
```
* Custom pip mapping
* When you create the `pip_overrides.json` file, it changes the installation of specific pip packages to installations defined by the user.
* Please refer to the `pip_overrides.json.template` file.
## Scanner
When you run the `scan.sh` script:
* It updates the `extension-node-map.json`.
* To do this, it pulls or clones the custom nodes listed in `custom-node-list.json` into `~/.tmp/default`.
* To skip this step, add the `--skip-update` option.
* If you want to specify a different path instead of `~/.tmp/default`, run `python scanner.py [path]` directly instead of `scan.sh`.
* It updates the `github-stats.json`.
* This uses the GitHub API, so set your token with `export GITHUB_TOKEN=your_token_here` to avoid quickly reaching the rate limit and malfunctioning.
* To skip this step, add the `--skip-update-stat` option.
* The `--skip-all` option applies both `--skip-update` and `--skip-stat-update`.
## Troubleshooting ## Troubleshooting
* If your `git.exe` is installed in a specific location other than system git, please install ComfyUI-Manager and run ComfyUI. Then, specify the path including the file name in `git_exe = ` in the ComfyUI-Manager/config.ini file that is generated. * If your `git.exe` is installed in a specific location other than system git, please install ComfyUI-Manager and run ComfyUI. Then, specify the path including the file name in `git_exe = ` in the ComfyUI-Manager/config.ini file that is generated.
* If updating ComfyUI-Manager itself fails, please go to the **ComfyUI-Manager** directory and execute the command `git update-ref refs/remotes/origin/main a361cc1 && git fetch --all && git pull`. * If updating ComfyUI-Manager itself fails, please go to the **ComfyUI-Manager** directory and execute the command `git update-ref refs/remotes/origin/main a361cc1 && git fetch --all && git pull`.
@ -340,31 +283,6 @@ When you run the `scan.sh` script:
* Edit `config.ini` file: add `windows_selector_event_loop_policy = True` * Edit `config.ini` file: add `windows_selector_event_loop_policy = True`
## Security policy
* Edit `config.ini` file: add `security_level = <LEVEL>`
* `strong`
* doesn't allow `high` and `middle` level risky feature
* `normal`
* doesn't allow `high` level risky feature if `--listen` is specified and not starts with `127.`
* `middle` level risky feature is available
* `weak`
* all feature is available
* `high` level risky features
* `Install via git url`, `pip install`
* Installation of custom nodes registered not in the `default channel`.
* Display terminal log
* `middle` level risky features
* Uninstall/Update/Fix custom nodes
* Installation of custom nodes registered in the `default channel`.
* Restore/Remove Snapshot
* Restart
* `low` level risky features
* Update ComfyUI
## TODO: Unconventional form of custom node list ## TODO: Unconventional form of custom node list
* https://github.com/diontimmer/Sample-Diffusion-ComfyUI-Extension * https://github.com/diontimmer/Sample-Diffusion-ComfyUI-Extension
@ -373,8 +291,7 @@ When you run the `scan.sh` script:
* https://github.com/StartHua/Comfyui_GPT_Story * https://github.com/StartHua/Comfyui_GPT_Story
* https://github.com/NielsGercama/comfyui_customsampling * https://github.com/NielsGercama/comfyui_customsampling
* https://github.com/wrightdaniel2017/ComfyUI-VideoLipSync * https://github.com/wrightdaniel2017/ComfyUI-VideoLipSync
* https://github.com/bxdsjs/ComfyUI-Image-preprocessing
* https://github.com/SMUELDigital/ComfyUI-ONSET
## Roadmap ## Roadmap
@ -388,8 +305,7 @@ When you run the `scan.sh` script:
- [ ] List of currently used custom nodes. - [ ] List of currently used custom nodes.
- [ ] Download support multiple model download. - [ ] Download support multiple model download.
- [ ] Model download via url. - [ ] Model download via url.
- [x] List sorting (custom nodes). - [ ] List sorting.
- [ ] List sorting (model).
- [ ] Provides description of node. - [ ] Provides description of node.

2412
__init__.py

File diff suppressed because it is too large Load Diff

15
alter-list.json

@ -199,21 +199,6 @@
"id":"https://github.com/abyz22/image_control", "id":"https://github.com/abyz22/image_control",
"tags":"BMAB", "tags":"BMAB",
"description": "This extension provides some alternative functionalities of the [a/sd-webui-bmab](https://github.com/portu-sim/sd-webui-bmab) extension." "description": "This extension provides some alternative functionalities of the [a/sd-webui-bmab](https://github.com/portu-sim/sd-webui-bmab) extension."
},
{
"id":"https://github.com/blepping/ComfyUI-sonar",
"tags":"sonar",
"description": "This extension provides some alternative functionalities of the [a/stable-diffusion-webui-sonar](https://github.com/Kahsolt/stable-diffusion-webui-sonar) extension."
},
{
"id":"https://github.com/AIFSH/ComfyUI-RVC",
"tags":"sonar",
"description": "a comfyui custom node for [a/Retrieval-based-Voice-Conversion-WebUI](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI.git), you can Voice-Conversion in comfyui now!"
},
{
"id":"https://github.com/portu-sim/comfyui-bmab",
"tags":"bmab",
"description": "a comfyui custom node for [a/sd-webui-bmab](https://github.com/portu-sim/sd-webui-bmab)"
} }
] ]
} }

21
check.bat

@ -1,21 +0,0 @@
@echo off
python json-checker.py "custom-node-list.json"
python json-checker.py "model-list.json"
python json-checker.py "alter-list.json"
python json-checker.py "extension-node-map.json"
python json-checker.py "node_db\new\custom-node-list.json"
python json-checker.py "node_db\new\model-list.json"
python json-checker.py "node_db\new\extension-node-map.json"
python json-checker.py "node_db\dev\custom-node-list.json"
python json-checker.py "node_db\dev\model-list.json"
python json-checker.py "node_db\dev\extension-node-map.json"
python json-checker.py "node_db\tutorial\custom-node-list.json"
python json-checker.py "node_db\tutorial\model-list.json"
python json-checker.py "node_db\tutorial\extension-node-map.json"
python json-checker.py "node_db\legacy\custom-node-list.json"
python json-checker.py "node_db\legacy\model-list.json"
python json-checker.py "node_db\legacy\extension-node-map.json"
python json-checker.py "node_db\forked\custom-node-list.json"
python json-checker.py "node_db\forked\model-list.json"
python json-checker.py "node_db\forked\extension-node-map.json"

1
check.sh

@ -5,7 +5,6 @@ files=(
"model-list.json" "model-list.json"
"alter-list.json" "alter-list.json"
"extension-node-map.json" "extension-node-map.json"
"github-stats.json"
"node_db/new/custom-node-list.json" "node_db/new/custom-node-list.json"
"node_db/new/model-list.json" "node_db/new/model-list.json"
"node_db/new/extension-node-map.json" "node_db/new/extension-node-map.json"

1018
cm-cli.py

File diff suppressed because it is too large Load Diff

4530
custom-node-list.json

File diff suppressed because it is too large Load Diff

146
docs/en/cm-cli.md

@ -1,146 +0,0 @@
# `cm-cli`: ComfyUI-Manager CLI
`cm-cli` is a tool that allows you to use various functions of ComfyUI-Manager from the command line without launching ComfyUI.
```
-= ComfyUI-Manager CLI (V2.24) =-
python cm-cli.py [OPTIONS]
OPTIONS:
[install|reinstall|uninstall|update|disable|enable|fix] node_name ... ?[--channel <channel name>] ?[--mode [remote|local|cache]]
[update|disable|enable|fix] all ?[--channel <channel name>] ?[--mode [remote|local|cache]]
[simple-show|show] [installed|enabled|not-installed|disabled|all|snapshot|snapshot-list] ?[--channel <channel name>] ?[--mode [remote|local|cache]]
save-snapshot ?[--output <snapshot .json/.yaml>]
restore-snapshot <snapshot .json/.yaml> ?[--pip-non-url] ?[--pip-non-local-url] ?[--pip-local-url]
cli-only-mode [enable|disable]
restore-dependencies
clear
```
## How To Use?
* You can execute it via `python cm-cli.py`.
* For example, if you want to update all custom nodes:
* In the ComfyUI-Manager directory, you can execute the command `python cm-cli.py update all`.
* If running from the ComfyUI directory, you can specify the path to cm-cli.py like this: `python custom_nodes/ComfyUI-Manager/cm-cli.py update all`.
## Prerequisite
* It must be run in the same Python environment as the one running ComfyUI.
* If using a venv, you must run it with the venv activated.
* If using a portable version, and you are in the directory with the run_nvidia_gpu.bat file, you should execute the command as follows:
`.\python_embeded\python.exe ComfyUI\custom_nodes\ComfyUI-Manager\cm-cli.py update all`
* The path for ComfyUI can be set with the COMFYUI_PATH environment variable. If omitted, a warning message will appear, and the path will be set relative to the installed location of ComfyUI-Manager:
```
WARN: The `COMFYUI_PATH` environment variable is not set. Assuming `custom_nodes/ComfyUI-Manager/../../` as the ComfyUI path.
```
## Features
### 1. --channel, --mode
* For viewing information and managing custom nodes, you can set the information database through --channel and --mode.
* For instance, executing the command `python cm-cli.py update all --channel recent --mode remote` will operate based on the latest information from remote rather than local data embedded in the current ComfyUI-Manager repo and will only target the list in the recent channel.
* --channel, --mode are only available with the commands `simple-show, show, install, uninstall, update, disable, enable, fix`.
### 2. Viewing Management Information
`[simple-show|show] [installed|enabled|not-installed|disabled|all|snapshot|snapshot-list] ?[--channel <channel name>] ?[--mode [remote|local|cache]]`
* `[show|simple-show]` - `show` provides detailed information, while `simple-show` displays information more simply.
Executing a command like `python cm-cli.py show installed` will display detailed information about the installed custom nodes.
```
-= ComfyUI-Manager CLI (V2.24) =-
FETCH DATA from: https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/custom-node-list.json
[ ENABLED ] ComfyUI-Manager (author: Dr.Lt.Data)
[ ENABLED ] ComfyUI-Impact-Pack (author: Dr.Lt.Data)
[ ENABLED ] ComfyUI-Inspire-Pack (author: Dr.Lt.Data)
[ ENABLED ] ComfyUI_experiments (author: comfyanonymous)
[ ENABLED ] ComfyUI-SAI_API (author: Stability-AI)
[ ENABLED ] stability-ComfyUI-nodes (author: Stability-AI)
[ ENABLED ] comfyui_controlnet_aux (author: Fannovel16)
[ ENABLED ] ComfyUI-Frame-Interpolation (author: Fannovel16)
[ DISABLED ] ComfyUI-Loopchain (author: Fannovel16)
```
Using a command like `python cm-cli.py simple-show installed` will simply display information about the installed custom nodes.
```
-= ComfyUI-Manager CLI (V2.24) =-
FETCH DATA from: https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/custom-node-list.json
ComfyUI-Manager
ComfyUI-Impact-Pack
ComfyUI-Inspire-Pack
ComfyUI_experiments
ComfyUI-SAI_API
stability-ComfyUI-nodes
comfyui_controlnet_aux
ComfyUI-Frame-Interpolation
ComfyUI-Loopchain
```
`[installed|enabled|not-installed|disabled|all|snapshot|snapshot-list]`
* `enabled`, `disabled`: Shows nodes that have been enabled or disabled among the installed custom nodes.
* `installed`: Shows all nodes that have been installed, regardless of whether they are enabled or disabled.
* `not-installed`: Shows a list of custom nodes that have not been installed.
* `all`: Shows a list of all custom nodes.
* `snapshot`: Displays snapshot information of the currently installed custom nodes. When viewed with `show`, it is displayed in JSON format, and with `simple-show`, it is displayed simply, along with the commit hash.
* `snapshot-list`: Shows a list of snapshot files stored in ComfyUI-Manager/snapshots.
### 3. Managing Custom Nodes
`[install|reinstall|uninstall|update|disable|enable|fix] node_name ... ?[--channel <channel name>] ?[--mode [remote|local|cache]]`
* You can apply management functions by listing the names of custom nodes, such as `python cm-cli.py install ComfyUI-Impact-Pack ComfyUI-Inspire-Pack ComfyUI_experiments`.
* The names of the custom nodes are as shown by `show` and are the names of the git repositories.
(Plans are to update the use of nicknames in the future.)
`[update|disable|enable|fix] all ?[--channel <channel name>] ?[--mode [remote|local|cache]]`
* The `update, disable, enable, fix` functions can be specified for all.
* Detailed Operations
* `install`: Installs the specified custom nodes.
* `reinstall`: Removes and then reinstalls the specified custom nodes.
* `uninstall`: Uninstalls the specified custom nodes.
* `update`: Updates the specified custom nodes.
* `disable`: Disables the specified custom nodes.
* `enable`: Enables the specified custom nodes.
* `fix`: Attempts to fix dependencies for the specified custom nodes.
### 4. Snapshot Management
* `python cm-cli.py save-snapshot [--output <snapshot .json/.yaml>]`: Saves the current snapshot.
* With `--output`, you can save a file in .yaml format to any specified path.
* `python cm-cli.py restore-snapshot <snapshot .json/.yaml>`: Restores to the specified snapshot.
* If a file exists at the snapshot path, that snapshot is loaded.
* If no file exists at the snapshot path, it is implicitly assumed to be in ComfyUI-Manager/snapshots.
* `--pip-non-url`: Restore for pip packages registered on PyPI.
* `--pip-non-local-url`: Restore for pip packages registered at web URLs.
* `--pip-local-url`: Restore for pip packages specified by local paths.
### 5. CLI Only Mode
You can set whether to use ComfyUI-Manager solely via CLI.
`cli-only-mode [enable|disable]`
* This mode can be used if you want to restrict the use of ComfyUI-Manager through the GUI for security or policy reasons.
* When CLI only mode is enabled, ComfyUI-Manager is loaded in a very restricted state, the internal web API is disabled, and the Manager button is not displayed in the main menu.
### 6. Dependency Restoration
`restore-dependencies`
* This command can be used if custom nodes are installed under the `ComfyUI/custom_nodes` path but their dependencies are not installed.
* It is useful when starting a new cloud instance, like colab, where dependencies need to be reinstalled and installation scripts re-executed.
* It can also be utilized if ComfyUI is reinstalled and only the custom_nodes path has been backed up and restored.
### 7. Clear
In the GUI, installations, updates, or snapshot restorations are scheduled to execute the next time ComfyUI is launched. The `clear` command clears this scheduled state, ensuring no pre-execution actions are applied.

149
docs/ko/cm-cli.md

@ -1,149 +0,0 @@
# `cm-cli`: ComfyUI-Manager CLI
`cm-cli` 는 ComfyUI를 실행시키지 않고 command line에서 ComfyUI-Manager의 여러가지 기능을 사용할 수 있도록 도와주는 도구입니다.
```
-= ComfyUI-Manager CLI (V2.24) =-
python cm-cli.py [OPTIONS]
OPTIONS:
[install|reinstall|uninstall|update|disable|enable|fix] node_name ... ?[--channel <channel name>] ?[--mode [remote|local|cache]]
[update|disable|enable|fix] all ?[--channel <channel name>] ?[--mode [remote|local|cache]]
[simple-show|show] [installed|enabled|not-installed|disabled|all|snapshot|snapshot-list] ?[--channel <channel name>] ?[--mode [remote|local|cache]]
save-snapshot ?[--output <snapshot .json/.yaml>]
restore-snapshot <snapshot .json/.yaml> ?[--pip-non-url] ?[--pip-non-local-url] ?[--pip-local-url]
cli-only-mode [enable|disable]
restore-dependencies
clear
```
## How To Use?
* `python cm-cli.py` 를 통해서 실행 시킬 수 있습니다.
* 예를 들어 custom node를 모두 업데이트 하고 싶다면
* ComfyUI-Manager경로 에서 `python cm-cli.py update all` 를 command를 실행할 수 있습니다.
* ComfyUI 경로에서 실행한다면, `python custom_nodes/ComfyUI-Manager/cm-cli.py update all` 와 같이 cm-cli.py 의 경로를 지정할 수도 있습니다.
## Prerequisite
* ComfyUI 를 실행하는 python과 동일한 python 환경에서 실행해야 합니다.
* venv를 사용할 경우 해당 venv를 activate 한 상태에서 실행해야 합니다.
* portable 버전을 사용할 경우 run_nvidia_gpu.bat 파일이 있는 경로인 경우, 다음과 같은 방식으로 코맨드를 실행해야 합니다.
`.\python_embeded\python.exe ComfyUI\custom_nodes\ComfyUI-Manager\cm-cli.py update all`
* ComfyUI 의 경로는 COMFYUI_PATH 환경 변수로 설정할 수 있습니다. 만약 생략할 경우 다음과 같은 경고 메시지가 나타나며, ComfyUI-Manager가 설치된 경로를 기준으로 상대 경로로 설정됩니다.
```
WARN: The `COMFYUI_PATH` environment variable is not set. Assuming `custom_nodes/ComfyUI-Manager/../../` as the ComfyUI path.
```
## Features
### 1. --channel, --mode
* 정보 보기 기능과 커스텀 노드 관리 기능의 경우는 --channel과 --mode를 통해 정보 DB를 설정할 수 있습니다.
* 예들 들어 `python cm-cli.py update all --channel recent --mode remote`와 같은 command를 실행할 경우, 현재 ComfyUI-Manager repo에 내장된 로컬의 정보가 아닌 remote의 최신 정보를 기준으로 동작하며, recent channel에 있는 목록을 대상으로만 동작합니다.
* --channel, --mode 는 `simple-show, show, install, uninstall, update, disable, enable, fix` command에서만 사용 가능합니다.
### 2. 관리 정보 보기
`[simple-show|show] [installed|enabled|not-installed|disabled|all|snapshot|snapshot-list] ?[--channel <channel name>] ?[--mode [remote|local|cache]]`
* `[show|simple-show]` - `show`는 상세하게 정보를 보여주며, `simple-show`는 간단하게 정보를 보여줍니다.
`python cm-cli.py show installed` 와 같은 코맨드를 실행하면 설치된 커스텀 노드의 정보를 상세하게 보여줍니다.
```
-= ComfyUI-Manager CLI (V2.24) =-
FETCH DATA from: https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/custom-node-list.json
[ ENABLED ] ComfyUI-Manager (author: Dr.Lt.Data)
[ ENABLED ] ComfyUI-Impact-Pack (author: Dr.Lt.Data)
[ ENABLED ] ComfyUI-Inspire-Pack (author: Dr.Lt.Data)
[ ENABLED ] ComfyUI_experiments (author: comfyanonymous)
[ ENABLED ] ComfyUI-SAI_API (author: Stability-AI)
[ ENABLED ] stability-ComfyUI-nodes (author: Stability-AI)
[ ENABLED ] comfyui_controlnet_aux (author: Fannovel16)
[ ENABLED ] ComfyUI-Frame-Interpolation (author: Fannovel16)
[ DISABLED ] ComfyUI-Loopchain (author: Fannovel16)
```
`python cm-cli.py simple-show installed` 와 같은 코맨드를 이용해서 설치된 커스텀 노드의 정보를 간단하게 보여줍니다.
```
-= ComfyUI-Manager CLI (V2.24) =-
FETCH DATA from: https://raw.githubusercontent.com/ltdrdata/ComfyUI-Manager/main/custom-node-list.json
ComfyUI-Manager
ComfyUI-Impact-Pack
ComfyUI-Inspire-Pack
ComfyUI_experiments
ComfyUI-SAI_API
stability-ComfyUI-nodes
comfyui_controlnet_aux
ComfyUI-Frame-Interpolation
ComfyUI-Loopchain
```
* `[installed|enabled|not-installed|disabled|all|snapshot|snapshot-list]`
* `enabled`, `disabled`: 설치된 커스텀 노드들 중 enable 되었거나, disable된 노드들을 보여줍니다.
* `installed`: enable, disable 여부와 상관없이 설치된 모든 노드를 보여줍니다
* `not-installed`: 설치되지 않은 커스텀 노드의 목록을 보여줍니다.
* `all`: 모든 커스텀 노드의 목록을 보여줍니다.
* `snapshot`: 현재 설치된 커스텀 노드의 snapshot 정보를 보여줍니다. `show`롤 통해서 볼 경우는 json 출력 형태로 보여주며, `simple-show`를 통해서 볼 경우는 간단하게, 커밋 해시와 함께 보여줍니다.
* `snapshot-list`: ComfyUI-Manager/snapshots 에 저장된 snapshot 파일의 목록을 보여줍니다.
### 3. 커스텀 노드 관리 하기
`[install|reinstall|uninstall|update|disable|enable|fix] node_name ... ?[--channel <channel name>] ?[--mode [remote|local|cache]]`
* `python cm-cli.py install ComfyUI-Impact-Pack ComfyUI-Inspire-Pack ComfyUI_experiments` 와 같이 커스텀 노드의 이름을 나열해서 관리 기능을 적용할 수 있습니다.
* 커스텀 노드의 이름은 `show`를 했을 때 보여주는 이름이며, git repository의 이름입니다.
(추후 nickname 을 사용가능하돌고 업데이트 할 예정입니다.)
`[update|disable|enable|fix] all ?[--channel <channel name>] ?[--mode [remote|local|cache]]`
* `update, disable, enable, fix` 기능은 all 로 지정 가능합니다.
* 세부 동작
* `install`: 지정된 커스텀 노드들을 설치합니다
* `reinstall`: 지정된 커스텀 노드를 삭제하고 재설치 합니다.
* `uninstall`: 지정된 커스텀 노드들을 삭제합니다.
* `update`: 지정된 커스텀 노드들을 업데이트합니다.
* `disable`: 지정된 커스텀 노드들을 비활성화합니다.
* `enable`: 지정된 커스텀 노드들을 활성화합니다.
* `fix`: 지정된 커스텀 노드의 의존성을 고치기 위한 시도를 합니다.
### 4. 스냅샷 관리 기능
* `python cm-cli.py save-snapshot ?[--output <snapshot .json/.yaml>]`: 현재의 snapshot을 저장합니다.
* --output 으로 임의의 경로에 .yaml 파일과 format으로 저장할 수 있습니다.
* `python cm-cli.py restore-snapshot <snapshot .json/.yaml>`: 지정된 snapshot으로 복구합니다.
* snapshot 경로에 파일이 존재하는 경우 해당 snapshot을 로드합니다.
* snapshot 경로에 파일이 존재하지 않는 경우 묵시적으로, ComfyUI-Manager/snapshots 에 있다고 가정합니다.
* `--pip-non-url`: PyPI 에 등록된 pip 패키지들에 대해서 복구를 수행
* `--pip-non-local-url`: web URL에 등록된 pip 패키지들에 대해서 복구를 수행
* `--pip-local-url`: local 경로를 지정하고 있는 pip 패키지들에 대해서 복구를 수행
### 5. CLI only mode
ComfyUI-Manager를 CLI로만 사용할 것인지를 설정할 수 있습니다.
`cli-only-mode [enable|disable]`
* security 혹은 policy 의 이유로 GUI 를 통한 ComfyUI-Manager 사용을 제한하고 싶은 경우 이 모드를 사용할 수 있습니다.
* CLI only mode를 적용할 경우 ComfyUI-Manager 가 매우 제한된 상태로 로드되어, 내부적으로 제공하는 web API가 비활성화 되며, 메인 메뉴에서도 Manager 버튼이 표시되지 않습니다.
### 6. 의존성 설치
`restore-dependencies`
* `ComfyUI/custom_nodes` 하위 경로에 커스텀 노드들이 설치되어 있긴 하지만, 의존성이 설치되지 않은 경우 사용할 수 있습니다.
* colab 과 같이 cloud instance를 새로 시작하는 경우 의존성 재설치 및 설치 스크립트가 재실행 되어야 하는 경우 사용합니다.
* ComfyUI을 재설치할 경우, custom_nodes 경로만 백업했다가 재설치 할 경우 활용 가능합니다.
### 7. clear
GUI에서 install, update를 하거나 snapshot 을 restore하는 경우 예약을 통해서 다음번 ComfyUI를 실행할 경우 실행되는 구조입니다. `clear` 는 이런 예약 상태를 clear해서, 아무런 사전 실행이 적용되지 않도록 합니다.

5523
extension-node-map.json

File diff suppressed because it is too large Load Diff

155
git_helper.py

@ -1,13 +1,9 @@
import subprocess
import sys import sys
import os import os
import traceback
import git import git
import configparser import configparser
import re import re
import json import json
import yaml
from torchvision.datasets.utils import download_url from torchvision.datasets.utils import download_url
from tqdm.auto import tqdm from tqdm.auto import tqdm
from git.remote import RemoteProgress from git.remote import RemoteProgress
@ -16,12 +12,6 @@ config_path = os.path.join(os.path.dirname(__file__), "config.ini")
nodelist_path = os.path.join(os.path.dirname(__file__), "custom-node-list.json") nodelist_path = os.path.join(os.path.dirname(__file__), "custom-node-list.json")
working_directory = os.getcwd() working_directory = os.getcwd()
if os.path.basename(working_directory) != 'custom_nodes':
print(f"WARN: This script should be executed in custom_nodes dir")
print(f"DBG: INFO {working_directory}")
print(f"DBG: INFO {sys.argv}")
# exit(-1)
class GitProgress(RemoteProgress): class GitProgress(RemoteProgress):
def __init__(self): def __init__(self):
@ -62,7 +52,7 @@ def gitcheck(path, do_fetch=False):
current_branch = repo.active_branch current_branch = repo.active_branch
branch_name = current_branch.name branch_name = current_branch.name
remote_name = current_branch.tracking_branch().remote_name remote_name = 'origin'
remote = repo.remote(name=remote_name) remote = repo.remote(name=remote_name)
if do_fetch: if do_fetch:
@ -114,7 +104,7 @@ def gitpull(path):
current_branch = repo.active_branch current_branch = repo.active_branch
branch_name = current_branch.name branch_name = current_branch.name
remote_name = current_branch.tracking_branch().remote_name remote_name = 'origin'
remote = repo.remote(name=remote_name) remote = repo.remote(name=remote_name)
remote.fetch() remote.fetch()
@ -142,7 +132,7 @@ def gitpull(path):
def checkout_comfyui_hash(target_hash): def checkout_comfyui_hash(target_hash):
repo_path = os.path.abspath(os.path.join(working_directory, '..')) # ComfyUI dir repo_path = os.path.join(working_directory, '..') # ComfyUI dir
repo = git.Repo(repo_path) repo = git.Repo(repo_path)
commit_hash = repo.head.commit.hexsha commit_hash = repo.head.commit.hexsha
@ -186,32 +176,24 @@ def checkout_custom_node_hash(git_custom_node_infos):
if repo_name.endswith('.disabled'): if repo_name.endswith('.disabled'):
repo_name = repo_name[:-9] repo_name = repo_name[:-9]
if repo_name not in repo_name_to_url: item = git_custom_node_infos[repo_name_to_url[repo_name]]
if not is_disabled: if item['disabled'] and is_disabled:
# should be disabled pass
print(f"DISABLE: {repo_name}") elif item['disabled'] and not is_disabled:
new_path = fullpath + ".disabled" # disable
os.rename(fullpath, new_path) print(f"DISABLE: {repo_name}")
need_checkout = False new_path = fullpath + ".disabled"
os.rename(fullpath, new_path)
pass
elif not item['disabled'] and is_disabled:
# enable
print(f"ENABLE: {repo_name}")
new_path = fullpath[:-9]
os.rename(fullpath, new_path)
fullpath = new_path
need_checkout = True
else: else:
item = git_custom_node_infos[repo_name_to_url[repo_name]] need_checkout = True
if item['disabled'] and is_disabled:
pass
elif item['disabled'] and not is_disabled:
# disable
print(f"DISABLE: {repo_name}")
new_path = fullpath + ".disabled"
os.rename(fullpath, new_path)
elif not item['disabled'] and is_disabled:
# enable
print(f"ENABLE: {repo_name}")
new_path = fullpath[:-9]
os.rename(fullpath, new_path)
fullpath = new_path
need_checkout = True
else:
need_checkout = True
if need_checkout: if need_checkout:
repo = git.Repo(fullpath) repo = git.Repo(fullpath)
@ -220,7 +202,6 @@ def checkout_custom_node_hash(git_custom_node_infos):
if commit_hash != item['hash']: if commit_hash != item['hash']:
print(f"CHECKOUT: {repo_name} [{item['hash']}]") print(f"CHECKOUT: {repo_name} [{item['hash']}]")
repo.git.checkout(item['hash']) repo.git.checkout(item['hash'])
except Exception: except Exception:
print(f"Failed to restore snapshots for the custom node '{path}'") print(f"Failed to restore snapshots for the custom node '{path}'")
@ -288,21 +269,8 @@ def apply_snapshot(target):
try: try:
path = os.path.join(os.path.dirname(__file__), 'snapshots', f"{target}") path = os.path.join(os.path.dirname(__file__), 'snapshots', f"{target}")
if os.path.exists(path): if os.path.exists(path):
if not target.endswith('.json') and not target.endswith('.yaml'): with open(path, 'r', encoding="UTF-8") as json_file:
print(f"Snapshot file not found: `{path}`") info = json.load(json_file)
print("APPLY SNAPSHOT: False")
return None
with open(path, 'r', encoding="UTF-8") as snapshot_file:
if target.endswith('.json'):
info = json.load(snapshot_file)
elif target.endswith('.yaml'):
info = yaml.load(snapshot_file, Loader=yaml.SafeLoader)
info = info['custom_nodes']
else:
# impossible case
print("APPLY SNAPSHOT: False")
return None
comfyui_hash = info['comfyui'] comfyui_hash = info['comfyui']
git_custom_node_infos = info['git_custom_nodes'] git_custom_node_infos = info['git_custom_nodes']
@ -313,81 +281,14 @@ def apply_snapshot(target):
invalidate_custom_node_file(file_custom_node_infos) invalidate_custom_node_file(file_custom_node_infos)
print("APPLY SNAPSHOT: True") print("APPLY SNAPSHOT: True")
if 'pips' in info: return
return info['pips']
else:
return None
print(f"Snapshot file not found: `{path}`") print(f"Snapshot file not found: `{path}`")
print("APPLY SNAPSHOT: False") print("APPLY SNAPSHOT: False")
return None
except Exception as e: except Exception as e:
print(e) print(e)
traceback.print_exc()
print("APPLY SNAPSHOT: False") print("APPLY SNAPSHOT: False")
return None
def restore_pip_snapshot(pips, options):
non_url = []
local_url = []
non_local_url = []
for k, v in pips.items():
if v == "":
non_url.append(k)
else:
if v.startswith('file:'):
local_url.append(v)
else:
non_local_url.append(v)
failed = []
if '--pip-non-url' in options:
# try all at once
res = 1
try:
res = subprocess.check_call([sys.executable, '-m', 'pip', 'install'] + non_url)
except:
pass
# fallback
if res != 0:
for x in non_url:
res = 1
try:
res = subprocess.check_call([sys.executable, '-m', 'pip', 'install', x])
except:
pass
if res != 0:
failed.append(x)
if '--pip-non-local-url' in options:
for x in non_local_url:
res = 1
try:
res = subprocess.check_call([sys.executable, '-m', 'pip', 'install', x])
except:
pass
if res != 0:
failed.append(x)
if '--pip-local-url' in options:
for x in local_url:
res = 1
try:
res = subprocess.check_call([sys.executable, '-m', 'pip', 'install', x])
except:
pass
if res != 0:
failed.append(x)
print(f"Installation failed for pip packages: {failed}")
def setup_environment(): def setup_environment():
config = configparser.ConfigParser() config = configparser.ConfigParser()
@ -409,15 +310,7 @@ try:
elif sys.argv[1] == "--pull": elif sys.argv[1] == "--pull":
gitpull(sys.argv[2]) gitpull(sys.argv[2])
elif sys.argv[1] == "--apply-snapshot": elif sys.argv[1] == "--apply-snapshot":
options = set() apply_snapshot(sys.argv[2])
for x in sys.argv:
if x in ['--pip-non-url', '--pip-local-url', '--pip-non-local-url']:
options.add(x)
pips = apply_snapshot(sys.argv[2])
if pips and len(options) > 0:
restore_pip_snapshot(pips, options)
sys.exit(0) sys.exit(0)
except Exception as e: except Exception as e:
print(e) print(e)

3354
github-stats.json

File diff suppressed because it is too large Load Diff

1200
glob/manager_core.py

File diff suppressed because it is too large Load Diff

1679
glob/manager_server.py

File diff suppressed because it is too large Load Diff

63
glob/manager_util.py

@ -1,63 +0,0 @@
try:
from distutils.version import StrictVersion
except:
print(f"[ComfyUI-Manager] 'distutils' package not found. Activating fallback mode for compatibility.")
class StrictVersion:
def __init__(self, version_string):
self.version_string = version_string
self.major = 0
self.minor = 0
self.patch = 0
self.pre_release = None
self.parse_version_string()
def parse_version_string(self):
parts = self.version_string.split('.')
if not parts:
raise ValueError("Version string must not be empty")
self.major = int(parts[0])
self.minor = int(parts[1]) if len(parts) > 1 else 0
self.patch = int(parts[2]) if len(parts) > 2 else 0
# Handling pre-release versions if present
if len(parts) > 3:
self.pre_release = parts[3]
def __str__(self):
version = f"{self.major}.{self.minor}.{self.patch}"
if self.pre_release:
version += f"-{self.pre_release}"
return version
def __eq__(self, other):
return (self.major, self.minor, self.patch, self.pre_release) == \
(other.major, other.minor, other.patch, other.pre_release)
def __lt__(self, other):
if (self.major, self.minor, self.patch) == (other.major, other.minor, other.patch):
return self.pre_release_compare(self.pre_release, other.pre_release) < 0
return (self.major, self.minor, self.patch) < (other.major, other.minor, other.patch)
@staticmethod
def pre_release_compare(pre1, pre2):
if pre1 == pre2:
return 0
if pre1 is None:
return 1
if pre2 is None:
return -1
return -1 if pre1 < pre2 else 1
def __le__(self, other):
return self == other or self < other
def __gt__(self, other):
return not self <= other
def __ge__(self, other):
return not self < other
def __ne__(self, other):
return not self == other

2
js/a1111-alter-downloader.js

@ -56,7 +56,7 @@ export class AlternativesInstaller extends ComfyDialog {
let data2 = data1.custom_node; let data2 = data1.custom_node;
if(!data2) if(!data2)
continue; continue;
let content = data1.tags.toLowerCase() + data1.description.toLowerCase() + data2.author.toLowerCase() + data2.description.toLowerCase() + data2.title.toLowerCase(); let content = data1.tags.toLowerCase() + data1.description.toLowerCase() + data2.author.toLowerCase() + data2.description.toLowerCase() + data2.title.toLowerCase();

11
js/cm-api.js

@ -41,18 +41,9 @@ async function tryInstallCustomNode(event) {
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(event.detail.target) body: JSON.stringify(event.detail.target)
}); });
if(response.status == 403) {
show_message('This action is not allowed with this security level configuration.');
return false;
}
} }
let response = await api.fetchApi("/manager/reboot"); api.fetchApi("/manager/reboot");
if(response.status == 403) {
show_message('This action is not allowed with this security level configuration.');
return false;
}
await sleep(300); await sleep(300);

116
js/comfyui-manager.js vendored

@ -15,8 +15,9 @@ import { CustomNodesInstaller } from "./custom-nodes-downloader.js";
import { AlternativesInstaller } from "./a1111-alter-downloader.js"; import { AlternativesInstaller } from "./a1111-alter-downloader.js";
import { SnapshotManager } from "./snapshot.js"; import { SnapshotManager } from "./snapshot.js";
import { ModelInstaller } from "./model-downloader.js"; import { ModelInstaller } from "./model-downloader.js";
import { manager_instance, setManagerInstance, install_via_git_url, install_pip, rebootAPI, free_models, show_message } from "./common.js"; import { manager_instance, setManagerInstance, install_via_git_url, install_pip, rebootAPI, free_models } from "./common.js";
import { ComponentBuilderDialog, load_components, set_component_policy, getPureName } from "./components-manager.js"; import { ComponentBuilderDialog, load_components, set_component_policy, getPureName } from "./component-builder.js";
import { ComponentsManager } from "./components-manager.js";
import { set_double_click_policy } from "./node_fixer.js"; import { set_double_click_policy } from "./node_fixer.js";
var docStyle = document.createElement('style'); var docStyle = document.createElement('style');
@ -147,13 +148,13 @@ docStyle.innerHTML = `
} }
.cm-notice-board > ul { .cm-notice-board > ul {
display: block; display: block;
list-style-type: disc; list-style-type: disc;
margin-block-start: 1em; margin-block-start: 1em;
margin-block-end: 1em; margin-block-end: 1em;
margin-inline-start: 0px; margin-inline-start: 0px;
margin-inline-end: 0px; margin-inline-end: 0px;
padding-inline-start: 40px; padding-inline-start: 40px;
} }
.cm-conflicted-nodes-text { .cm-conflicted-nodes-text {
@ -183,6 +184,10 @@ docStyle.innerHTML = `
overflow-x: hidden; overflow-x: hidden;
overflow: auto; overflow: auto;
} }
#components-grid tr {
height: 50px;
}
`; `;
document.head.appendChild(docStyle); document.head.appendChild(docStyle);
@ -226,16 +231,6 @@ const style = `
font-size: 17px !important; font-size: 17px !important;
} }
.cm-button-red {
width: 310px;
height: 30px;
position: relative;
overflow: hidden;
font-size: 17px !important;
background-color: #500000 !important;
color: white !important;
}
.cm-experimental-button { .cm-experimental-button {
width: 290px; width: 290px;
height: 30px; height: 30px;
@ -388,7 +383,7 @@ await init_badge_mode();
await init_share_option(); await init_share_option();
async function fetchNicknames() { async function fetchNicknames() {
const response1 = await api.fetchApi(`/customnode/getmappings?mode=nickname`); const response1 = await api.fetchApi(`/customnode/getmappings?mode=local`);
const mappings = await response1.json(); const mappings = await response1.json();
let result = {}; let result = {};
@ -520,21 +515,25 @@ async function updateComfyUI() {
const response = await api.fetchApi('/comfyui_manager/update_comfyui'); const response = await api.fetchApi('/comfyui_manager/update_comfyui');
if (response.status == 400) { if (response.status == 400) {
show_message('Failed to update ComfyUI.'); app.ui.dialog.show('Failed to update ComfyUI.');
app.ui.dialog.element.style.zIndex = 10010;
return false; return false;
} }
if (response.status == 201) { if (response.status == 201) {
show_message('ComfyUI has been successfully updated.'); app.ui.dialog.show('ComfyUI has been successfully updated.');
app.ui.dialog.element.style.zIndex = 10010;
} }
else { else {
show_message('ComfyUI is already up to date with the latest version.'); app.ui.dialog.show('ComfyUI is already up to date with the latest version.');
app.ui.dialog.element.style.zIndex = 10010;
} }
return true; return true;
} }
catch (exception) { catch (exception) {
show_message(`Failed to update ComfyUI / ${exception}`); app.ui.dialog.show(`Failed to update ComfyUI / ${exception}`);
app.ui.dialog.element.style.zIndex = 10010;
return false; return false;
} }
finally { finally {
@ -556,12 +555,13 @@ async function fetchUpdates(update_check_checkbox) {
const response = await api.fetchApi(`/customnode/fetch_updates?mode=${mode}`); const response = await api.fetchApi(`/customnode/fetch_updates?mode=${mode}`);
if (response.status != 200 && response.status != 201) { if (response.status != 200 && response.status != 201) {
show_message('Failed to fetch updates.'); app.ui.dialog.show('Failed to fetch updates.');
app.ui.dialog.element.style.zIndex = 10010;
return false; return false;
} }
if (response.status == 201) { if (response.status == 201) {
show_message("There is an updated extension available.<BR><BR><P><B>NOTE:<BR>Fetch Updates is not an update.<BR>Please update from <button id='cm-install-customnodes-button'>Install Custom Nodes</button> </B></P>"); app.ui.dialog.show("There is an updated extension available.<BR><BR><P><B>NOTE:<BR>Fetch Updates is not an update.<BR>Please update from <button id='cm-install-customnodes-button'>Install Custom Nodes</button> </B></P>");
const button = document.getElementById('cm-install-customnodes-button'); const button = document.getElementById('cm-install-customnodes-button');
button.addEventListener("click", button.addEventListener("click",
@ -575,16 +575,19 @@ async function fetchUpdates(update_check_checkbox) {
} }
); );
app.ui.dialog.element.style.zIndex = 10010;
update_check_checkbox.checked = false; update_check_checkbox.checked = false;
} }
else { else {
show_message('All extensions are already up-to-date with the latest versions.'); app.ui.dialog.show('All extensions are already up-to-date with the latest versions.');
app.ui.dialog.element.style.zIndex = 10010;
} }
return true; return true;
} }
catch (exception) { catch (exception) {
show_message(`Failed to update custom nodes / ${exception}`); app.ui.dialog.show(`Failed to update custom nodes / ${exception}`);
app.ui.dialog.element.style.zIndex = 10010;
return false; return false;
} }
finally { finally {
@ -607,16 +610,11 @@ async function updateAll(update_check_checkbox, manager_dialog) {
const response1 = await api.fetchApi('/comfyui_manager/update_comfyui'); const response1 = await api.fetchApi('/comfyui_manager/update_comfyui');
const response2 = await api.fetchApi(`/customnode/update_all?mode=${mode}`); const response2 = await api.fetchApi(`/customnode/update_all?mode=${mode}`);
if (response2.status == 403) { if (response1.status != 200 && response2.status != 201) {
show_message('This action is not allowed with this security level configuration.'); app.ui.dialog.show('Failed to update ComfyUI or several extensions.<BR><BR>See terminal log.<BR>');
app.ui.dialog.element.style.zIndex = 10010;
return false; return false;
} }
if (response1.status == 400 || response2.status == 400) {
show_message('Failed to update ComfyUI or several extensions.<BR><BR>See terminal log.<BR>');
return false;
}
if(response1.status == 201 || response2.status == 201) { if(response1.status == 201 || response2.status == 201) {
const update_info = await response2.json(); const update_info = await response2.json();
@ -630,28 +628,32 @@ async function updateAll(update_check_checkbox, manager_dialog) {
updated_list = "<BR>UPDATED: "+update_info.updated.join(", "); updated_list = "<BR>UPDATED: "+update_info.updated.join(", ");
} }
show_message( app.ui.dialog.show(
"ComfyUI and all extensions have been updated to the latest version.<BR>To apply the updated custom node, please <button class='cm-small-button' id='cm-reboot-button5'>RESTART</button> ComfyUI. And refresh browser.<BR>" "ComfyUI and all extensions have been updated to the latest version.<BR>To apply the updated custom node, please <button class='cm-small-button' id='cm-reboot-button'>RESTART</button> ComfyUI. And refresh browser.<BR>"
+failed_list +failed_list
+updated_list +updated_list
); );
const rebootButton = document.getElementById('cm-reboot-button5'); const rebootButton = document.getElementById('cm-reboot-button');
rebootButton.addEventListener("click", rebootButton.addEventListener("click",
function() { function() {
if(rebootAPI()) { if(rebootAPI()) {
manager_dialog.close(); manager_dialog.close();
} }
}); });
app.ui.dialog.element.style.zIndex = 10010;
} }
else { else {
show_message('ComfyUI and all extensions are already up-to-date with the latest versions.'); app.ui.dialog.show('ComfyUI and all extensions are already up-to-date with the latest versions.');
app.ui.dialog.element.style.zIndex = 10010;
} }
return true; return true;
} }
catch (exception) { catch (exception) {
show_message(`Failed to update ComfyUI or several extensions / ${exception}`); app.ui.dialog.show(`Failed to update ComfyUI or several extensions / ${exception}`);
app.ui.dialog.element.style.zIndex = 10010;
return false; return false;
} }
finally { finally {
@ -772,14 +774,7 @@ class ManagerMenuDialog extends ComfyDialog {
AlternativesInstaller.instance = new AlternativesInstaller(app, self); AlternativesInstaller.instance = new AlternativesInstaller(app, self);
AlternativesInstaller.instance.show(); AlternativesInstaller.instance.show();
} }
}), })
$el("br", {}, []),
$el("button.cm-button-red", {
type: "button",
textContent: "Restart",
onclick: () => rebootAPI()
}),
]; ];
return res; return res;
@ -918,7 +913,7 @@ class ManagerMenuDialog extends ComfyDialog {
}); });
let dbl_click_policy_combo = document.createElement("select"); let dbl_click_policy_combo = document.createElement("select");
dbl_click_policy_combo.setAttribute("title", "Sets the behavior when you double-click the title area of a node."); dbl_click_policy_combo.setAttribute("title", "When loading the workflow, configure which version of the component to use.");
dbl_click_policy_combo.className = "cm-menu-combo"; dbl_click_policy_combo.className = "cm-menu-combo";
dbl_click_policy_combo.appendChild($el('option', { value: 'none', text: 'Double-Click: None' }, [])); dbl_click_policy_combo.appendChild($el('option', { value: 'none', text: 'Double-Click: None' }, []));
dbl_click_policy_combo.appendChild($el('option', { value: 'copy-all', text: 'Double-Click: Copy All Connections' }, [])); dbl_click_policy_combo.appendChild($el('option', { value: 'copy-all', text: 'Double-Click: Copy All Connections' }, []));
@ -999,7 +994,17 @@ class ManagerMenuDialog extends ComfyDialog {
type: "button", type: "button",
textContent: "Unload models", textContent: "Unload models",
onclick: () => { free_models(); } onclick: () => { free_models(); }
}) }),
$el("button.cm-experimental-button", {
type: "button",
textContent: "Manage Components",
onclick:
() => {
if(!ComponentsManager.instance)
ComponentsManager.instance = new ComponentsManager(app, self);
ComponentsManager.instance.show();
}
}),
]), ]),
]; ];
} }
@ -1220,15 +1225,6 @@ class ManagerMenuDialog extends ComfyDialog {
modifyButtonStyle(url); modifyButtonStyle(url);
}, },
}, },
{
title: "Open 'esheep'",
callback: () => {
const url = "https://www.esheep.com";
localStorage.setItem("wg_last_visited", url);
window.open(url, url);
modifyButtonStyle(url);
},
},
{ {
title: "Close", title: "Close",
callback: () => { callback: () => {

33
js/comfyui-share-common.js vendored

@ -164,29 +164,6 @@ export function parseURLPath(urlPath) {
} }
export const shareToEsheep= () => {
app.graphToPrompt()
.then(prompt => {
const nodes = app.graph._nodes
const { potential_outputs, potential_output_nodes } = getPotentialOutputsAndOutputNodes(nodes);
const workflow = prompt['workflow']
api.fetchApi(`/manager/set_esheep_workflow_and_images`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
workflow: workflow,
images: potential_outputs
})
}).then(response => {
var domain = window.location.hostname;
var port = window.location.port;
port = port || (window.location.protocol === 'http:' ? '80' : window.location.protocol === 'https:' ? '443' : '');
var full_domin = domain + ':' + port
window.open('https://www.esheep.com/app/workflow_upload?from_local='+ full_domin, '_blank');
});
})
}
export const showOpenArtShareDialog = () => { export const showOpenArtShareDialog = () => {
if (!OpenArtShareDialog.instance) { if (!OpenArtShareDialog.instance) {
OpenArtShareDialog.instance = new OpenArtShareDialog(); OpenArtShareDialog.instance = new OpenArtShareDialog();
@ -306,16 +283,6 @@ export class ShareDialogChooser extends ComfyDialog {
}) })
} }
}, },
{
key: "esheep",
textContent: "eSheep",
website: "https://www.esheep.com",
description: "Share & download thousands of ComfyUI workflows on <a style='color:white;' href='https://www.esheep.com' target='_blank'>esheep.com</a>",
onclick: () => {
shareToEsheep();
this.close();
}
},
]; ];
function createShareButtonsWithDescriptions() { function createShareButtonsWithDescriptions() {

4
js/comfyui-share-openart.js vendored

@ -481,6 +481,10 @@ export class OpenArtShareDialog extends ComfyDialog {
if (this.uploadImagesInput.files.length === 0) { if (this.uploadImagesInput.files.length === 0) {
throw new Error("No thumbnail uploaded"); throw new Error("No thumbnail uploaded");
} }
if (this.uploadImagesInput.files.length === 0) {
throw new Error("No thumbnail uploaded");
}
} }
} }

77
js/common.js

@ -1,11 +1,6 @@
import { app } from "../../scripts/app.js"; import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js"; import { api } from "../../scripts/api.js";
export function show_message(msg) {
app.ui.dialog.show(msg);
app.ui.dialog.element.style.zIndex = 10010;
}
export async function sleep(ms) { export async function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms)); return new Promise(resolve => setTimeout(resolve, ms));
} }
@ -52,20 +47,6 @@ export async function install_checked_custom_node(grid_rows, target_i, caller, m
body: JSON.stringify(target) body: JSON.stringify(target)
}); });
if(response.status == 403) {
show_message('This action is not allowed with this security level configuration.');
caller.updateMessage('');
await caller.invalidateControl();
return;
}
if(response.status == 404) {
show_message('With the current security level configuration, only custom nodes from the <B>"default channel"</B> can be installed.');
caller.updateMessage('');
await caller.invalidateControl();
return;
}
if(response.status == 400) { if(response.status == 400) {
show_message(`${mode} failed: ${target.title}`); show_message(`${mode} failed: ${target.title}`);
continue; continue;
@ -86,7 +67,7 @@ export async function install_checked_custom_node(grid_rows, target_i, caller, m
} }
await caller.invalidateControl(); await caller.invalidateControl();
caller.updateMessage("<BR>To apply the installed/updated/disabled/enabled custom node, please <button id='cm-reboot-button1' class='cm-small-button'>RESTART</button> ComfyUI. And refresh browser.", 'cm-reboot-button1'); caller.updateMessage("<BR>To apply the installed/updated/disabled/enabled custom node, please <button id='cm-reboot-button' class='cm-small-button'>RESTART</button> ComfyUI. And refresh browser.", 'cm-reboot-button');
} }
}; };
@ -108,26 +89,21 @@ export async function install_pip(packages) {
if(packages.includes('&')) if(packages.includes('&'))
app.ui.dialog.show(`Invalid PIP package enumeration: '${packages}'`); app.ui.dialog.show(`Invalid PIP package enumeration: '${packages}'`);
const res = await api.fetchApi("/customnode/install/pip", { const res = await api.fetchApi(`/customnode/install/pip?packages=${packages}`);
method: "POST",
body: packages,
});
if(res.status == 403) {
show_message('This action is not allowed with this security level configuration.');
return;
}
if(res.status == 200) { if(res.status == 200) {
show_message(`PIP package installation is processed.<br>To apply the pip packages, please click the <button id='cm-reboot-button3'><font size='3px'>RESTART</font></button> button in ComfyUI.`); app.ui.dialog.show(`PIP package installation is processed.<br>To apply the pip packages, please click the <button id='cm-reboot-button'><font size='3px'>RESTART</font></button> button in ComfyUI.`);
const rebootButton = document.getElementById('cm-reboot-button3'); const rebootButton = document.getElementById('cm-reboot-button');
const self = this; const self = this;
rebootButton.addEventListener("click", rebootAPI); rebootButton.addEventListener("click", rebootAPI);
app.ui.dialog.element.style.zIndex = 10010;
} }
else { else {
show_message(`Failed to install '${packages}'<BR>See terminal log.`); app.ui.dialog.show(`Failed to install '${packages}'<BR>See terminal log.`);
app.ui.dialog.element.style.zIndex = 10010;
} }
} }
@ -137,26 +113,20 @@ export async function install_via_git_url(url, manager_dialog) {
} }
if(!isValidURL(url)) { if(!isValidURL(url)) {
show_message(`Invalid Git url '${url}'`); app.ui.dialog.show(`Invalid Git url '${url}'`);
app.ui.dialog.element.style.zIndex = 10010;
return; return;
} }
show_message(`Wait...<BR><BR>Installing '${url}'`); app.ui.dialog.show(`Wait...<BR><BR>Installing '${url}'`);
app.ui.dialog.element.style.zIndex = 10010;
const res = await api.fetchApi("/customnode/install/git_url", {
method: "POST",
body: url,
});
if(res.status == 403) { const res = await api.fetchApi(`/customnode/install/git_url?url=${url}`);
show_message('This action is not allowed with this security level configuration.');
return;
}
if(res.status == 200) { if(res.status == 200) {
show_message(`'${url}' is installed<BR>To apply the installed custom node, please <button id='cm-reboot-button4'><font size='3px'>RESTART</font></button> ComfyUI.`); app.ui.dialog.show(`'${url}' is installed<BR>To apply the installed custom node, please <button id='cm-reboot-button'><font size='3px'>RESTART</font></button> ComfyUI.`);
const rebootButton = document.getElementById('cm-reboot-button4'); const rebootButton = document.getElementById('cm-reboot-button');
const self = this; const self = this;
rebootButton.addEventListener("click", rebootButton.addEventListener("click",
@ -165,9 +135,12 @@ export async function install_via_git_url(url, manager_dialog) {
manager_dialog.close(); manager_dialog.close();
} }
}); });
app.ui.dialog.element.style.zIndex = 10010;
} }
else { else {
show_message(`Failed to install '${url}'<BR>See terminal log.`); app.ui.dialog.show(`Failed to install '${url}'<BR>See terminal log.`);
app.ui.dialog.element.style.zIndex = 10010;
} }
} }
@ -175,13 +148,19 @@ export async function free_models() {
let res = await api.fetchApi(`/free`, { let res = await api.fetchApi(`/free`, {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: '{"unload_models": true}' body: '{}'
}); });
if(res.status == 200) { if(res.status == 200) {
show_message('Models have been unloaded.') app.ui.dialog.show('Models have been unloaded.')
} }
else { else {
show_message('Unloading of models failed.<BR><BR>Installed ComfyUI may be an outdated version.') app.ui.dialog.show('Unloading of models failed.<BR><BR>Installed ComfyUI may be an outdated version.')
} }
app.ui.dialog.element.style.zIndex = 10010;
} }
export function show_message(msg) {
app.ui.dialog.show(msg);
app.ui.dialog.element.style.zIndex = 10010;
}

839
js/component-builder.js

@ -0,0 +1,839 @@
import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js"
import { sleep, show_message } from "./common.js";
import { GroupNodeConfig, GroupNodeHandler } from "../../extensions/core/groupNode.js";
import { ComfyDialog, $el } from "../../scripts/ui.js";
let pack_map = {};
let rpack_map = {};
export function isInstalled(name) {
return rpack_map[name] != undefined;
}
export function getPureName(node) {
// group nodes/
let category = null;
if(node.category) {
category = node.category.substring(12);
}
else {
category = node.constructor.category?.substring(12);
}
if(category) {
let purename = node.comfyClass.substring(category.length+1);
return purename;
}
else if(node.comfyClass.startsWith('workflow/')) {
return node.comfyClass.substring(9);
}
else {
return node.comfyClass;
}
}
function isValidVersionString(version) {
const versionPattern = /^(\d+)\.(\d+)(\.(\d+))?$/;
const match = version.match(versionPattern);
return match !== null &&
parseInt(match[1], 10) >= 0 &&
parseInt(match[2], 10) >= 0 &&
(!match[3] || parseInt(match[4], 10) >= 0);
}
function register_pack_map(name, data) {
if(data.packname) {
pack_map[data.packname] = name;
rpack_map[name] = data;
}
else {
rpack_map[name] = data;
}
}
function storeGroupNode(name, data, register=true) {
let extra = app.graph.extra;
if (!extra) app.graph.extra = extra = {};
let groupNodes = extra.groupNodes;
if (!groupNodes) extra.groupNodes = groupNodes = {};
groupNodes[name] = data;
if(register) {
register_pack_map(name, data);
}
}
export async function load_components() {
let data = await api.fetchApi('/manager/component/loads', {method: "POST"});
let components = await data.json();
let start_time = Date.now();
let failed = [];
let failed2 = [];
for(let name in components) {
if(app.graph.extra?.groupNodes?.[name]) {
if(data) {
let data = components[name];
let category = data.packname;
if(data.category) {
category += "/" + data.category;
}
if(category == '') {
category = 'components';
}
const config = new GroupNodeConfig(name, data);
await config.registerType(category);
register_pack_map(name, data);
continue;
}
}
let nodeData = components[name];
storeGroupNode(name, nodeData);
const config = new GroupNodeConfig(name, nodeData);
while(true) {
try {
let category = nodeData.packname;
if(nodeData.category) {
category += "/" + nodeData.category;
}
if(category == '') {
category = 'components';
}
await config.registerType(category);
register_pack_map(name, nodeData);
break;
}
catch {
let elapsed_time = Date.now() - start_time;
if (elapsed_time > 5000) {
failed.push(name);
break;
} else {
await sleep(100);
}
}
}
}
// fallback1
for(let i in failed) {
let name = failed[i];
if(app.graph.extra?.groupNodes?.[name]) {
continue;
}
let nodeData = components[name];
storeGroupNode(name, nodeData);
const config = new GroupNodeConfig(name, nodeData);
while(true) {
try {
let category = nodeData.packname;
if(nodeData.workflow.category) {
category += "/" + nodeData.category;
}
if(category == '') {
category = 'components';
}
await config.registerType(category);
register_pack_map(name, nodeData);
break;
}
catch {
let elapsed_time = Date.now() - start_time;
if (elapsed_time > 10000) {
failed2.push(name);
break;
} else {
await sleep(100);
}
}
}
}
// fallback2
for(let name in failed2) {
let name = failed2[i];
let nodeData = components[name];
storeGroupNode(name, nodeData);
const config = new GroupNodeConfig(name, nodeData);
while(true) {
try {
let category = nodeData.workflow.packname;
if(nodeData.workflow.category) {
category += "/" + nodeData.category;
}
if(category == '') {
category = 'components';
}
await config.registerType(category);
register_pack_map(name, nodeData);
break;
}
catch {
let elapsed_time = Date.now() - start_time;
if (elapsed_time > 30000) {
failed.push(name);
break;
} else {
await sleep(100);
}
}
}
}
}
export async function uninstall_component(nodename, packname) {
let body =
{
"name": nodename,
"packname": packname
};
const res = await api.fetchApi('/manager/component/remove', {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
if(res.status == 200) {
delete rpack_map[nodename];
}
else {
console.log(`Failed to remove component: ${nodename}`);
}
}
export async function save_as_component(node, version, author, prefix, nodename, packname, category) {
let component_name = nodename;
if(prefix) {
component_name = `${prefix}::${nodename}`;
}
let subgraph = app.graph.extra?.groupNodes?.[component_name];
if(!subgraph) {
subgraph = app.graph.extra?.groupNodes?.[getPureName(node)];
}
subgraph.version = version;
subgraph.author = author;
subgraph.datetime = Date.now();
subgraph.packname = packname;
subgraph.category = category;
let body =
{
name: component_name,
workflow: subgraph
};
pack_map[packname] = component_name;
rpack_map[component_name] = subgraph;
const res = await api.fetchApi('/manager/component/save', {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
if(res.status == 200) {
storeGroupNode(component_name, subgraph);
const config = new GroupNodeConfig(component_name, subgraph);
let category = body.workflow.packname;
if(body.workflow.category) {
category += "/" + body.workflow.category;
}
if(category == '') {
category = 'components';
}
await config.registerType(category);
let path = await res.text();
show_message(`Component '${component_name}' is saved into:\n${path}`);
}
else
show_message(`Failed to save component.`);
}
async function import_component(component_name, component, mode) {
if(mode) {
let body =
{
name: component_name,
workflow: component
};
const res = await api.fetchApi('/manager/component/save', {
method: "POST",
headers: { "Content-Type": "application/json", },
body: JSON.stringify(body)
});
}
let category = component.packname;
if(component.category) {
category += "/" + component.category;
}
if(category == '') {
category = 'components';
}
storeGroupNode(component_name, component);
const config = new GroupNodeConfig(component_name, component);
await config.registerType(category);
}
function restore_to_loaded_component(component_name) {
if(rpack_map[component_name]) {
let component = rpack_map[component_name];
storeGroupNode(component_name, component, false);
const config = new GroupNodeConfig(component_name, component);
config.registerType(component.category);
}
}
// Using a timestamp prevents duplicate pastes and ensures the prevention of re-deletion of litegrapheditor_clipboard.
let last_paste_timestamp = null;
function versionCompare(v1, v2) {
let ver1;
let ver2;
if(v1 && v1 != '') {
ver1 = v1.split('.');
ver1[0] = parseInt(ver1[0]);
ver1[1] = parseInt(ver1[1]);
if(ver1.length == 2)
ver1.push(0);
else
ver1[2] = parseInt(ver2[2]);
}
else {
ver1 = [0,0,0];
}
if(v2 && v2 != '') {
ver2 = v2.split('.');
ver2[0] = parseInt(ver2[0]);
ver2[1] = parseInt(ver2[1]);
if(ver2.length == 2)
ver2.push(0);
else
ver2[2] = parseInt(ver2[2]);
}
else {
ver2 = [0,0,0];
}
if(ver1[0] > ver2[0])
return -1;
else if(ver1[0] < ver2[0])
return 1;
if(ver1[1] > ver2[1])
return -1;
else if(ver1[1] < ver2[1])
return 1;
if(ver1[2] > ver2[2])
return -1;
else if(ver1[2] < ver2[2])
return 1;
return 0;
}
function checkVersion(name, component) {
let msg = '';
if(rpack_map[name]) {
let old_version = rpack_map[name].version;
if(!old_version || old_version == '') {
msg = ` '${name}' Upgrade (V0.0 -> V${component.version})`;
}
else {
let c = versionCompare(old_version, component.version);
if(c < 0) {
msg = ` '${name}' Downgrade (V${old_version} -> V${component.version})`;
}
else if(c > 0) {
msg = ` '${name}' Upgrade (V${old_version} -> V${component.version})`;
}
else {
msg = ` '${name}' Same version (V${component.version})`;
}
}
}
else {
msg = `'${name}' NEW (V${component.version})`;
}
return msg;
}
function handle_import_components(components) {
let msg = 'Components:\n';
let cnt = 0;
for(let name in components) {
let component = components[name];
let v = checkVersion(name, component);
if(cnt < 10) {
msg += v + '\n';
}
else if (cnt == 10) {
msg += '...\n';
}
else {
// do nothing
}
cnt++;
}
let last_name = null;
msg += '\nWill you load components?\n';
if(confirm(msg)) {
let mode = confirm('\nWill you save components?\n(cancel=load without save)');
for(let name in components) {
let component = components[name];
import_component(name, component, mode);
last_name = name;
}
if(mode) {
show_message('Components are saved.');
}
else {
show_message('Components are loaded.');
}
}
if(cnt == 1 && last_name) {
const node = LiteGraph.createNode(`workflow/${last_name}`);
node.pos = [app.canvas.graph_mouse[0], app.canvas.graph_mouse[1]];
app.canvas.graph.add(node, false);
}
}
function handlePaste(e) {
let data = (e.clipboardData || window.clipboardData);
const items = data.items;
for(const item of items) {
if(item.kind == 'string' && item.type == 'text/plain') {
data = data.getData("text/plain");
try {
let json_data = JSON.parse(data);
if(json_data.kind == 'ComfyUI Components' && last_paste_timestamp != json_data.timestamp) {
last_paste_timestamp = json_data.timestamp;
handle_import_components(json_data.components);
// disable paste node
localStorage.removeItem("litegrapheditor_clipboard", null);
}
else {
console.log('This components are already pasted: ignored');
}
}
catch {
// nothing to do
}
}
}
}
document.addEventListener("paste", handlePaste);
export class ComponentBuilderDialog extends ComfyDialog {
constructor() {
super();
}
clear() {
while (this.element.children.length) {
this.element.removeChild(this.element.children[0]);
}
}
show() {
this.invalidateControl();
this.element.style.display = "block";
this.element.style.zIndex = 10001;
this.element.style.width = "500px";
this.element.style.height = "480px";
}
invalidateControl() {
this.clear();
let self = this;
const close_button = $el("button", { id: "cm-close-button", type: "button", textContent: "Close", onclick: () => self.close() });
this.save_button = $el("button",
{ id: "cm-save-button", type: "button", textContent: "Save", onclick: () =>
{
save_as_component(self.target_node, self.version_string.value.trim(), self.author.value.trim(), self.node_prefix.value.trim(),
self.getNodeName(), self.getPackName(), self.category.value.trim());
}
});
let default_nodename = getPureName(this.target_node).trim();
let groupNode = app.graph.extra.groupNodes[default_nodename];
let default_packname = groupNode.packname;
if(!default_packname) {
default_packname = '';
}
let default_category = groupNode.category;
if(!default_category) {
default_category = '';
}
this.default_ver = groupNode.version;
if(!this.default_ver) {
this.default_ver = '0.0';
}
let default_author = groupNode.author;
if(!default_author) {
default_author = '';
}
let delimiterIndex = default_nodename.indexOf('::');
let default_prefix = "";
if(delimiterIndex != -1) {
default_prefix = default_nodename.substring(0, delimiterIndex);
default_nodename = default_nodename.substring(delimiterIndex + 2);
}
if(!default_prefix) {
this.save_button.disabled = true;
}
this.pack_list = this.createPackListCombo();
let version_string = this.createLabeledInput('input version (e.g. 1.0)', '*Version : ', this.default_ver);
this.version_string = version_string[1];
this.version_string.disabled = true;
let author = this.createLabeledInput('input author (e.g. Dr.Lt.Data)', 'Author : ', default_author);
this.author = author[1];
let node_prefix = this.createLabeledInput('input node prefix (e.g. mypack)', '*Prefix : ', default_prefix);
this.node_prefix = node_prefix[1];
let manual_nodename = this.createLabeledInput('input node name (e.g. MAKE_BASIC_PIPE)', 'Nodename : ', default_nodename);
this.manual_nodename = manual_nodename[1];
let manual_packname = this.createLabeledInput('input pack name (e.g. mypack)', 'Packname : ', default_packname);
this.manual_packname = manual_packname[1];
let category = this.createLabeledInput('input category (e.g. util/pipe)', 'Category : ', default_category);
this.category = category[1];
this.node_label = this.createNodeLabel();
let author_mode = this.createAuthorModeCheck();
this.author_mode = author_mode[0];
const content =
$el("div.comfy-modal-content",
[
$el("tr.cm-title", {}, [
$el("font", {size:6, color:"white"}, [`ComfyUI-Manager: Component Builder`])]
),
$el("br", {}, []),
$el("div.cm-menu-container",
[
author_mode[0],
author_mode[1],
category[0],
author[0],
node_prefix[0],
manual_nodename[0],
manual_packname[0],
version_string[0],
this.pack_list,
$el("br", {}, []),
this.node_label
]),
$el("br", {}, []),
this.save_button,
close_button,
]
);
content.style.width = '100%';
content.style.height = '100%';
this.element = $el("div.comfy-modal", { id:'cm-manager-dialog', parent: document.body }, [ content ]);
}
validateInput() {
let msg = "";
if(!isValidVersionString(this.version_string.value)) {
msg += 'Invalid version string: '+event.value+"\n";
}
if(this.node_prefix.value.trim() == '') {
msg += 'Node prefix cannot be empty\n';
}
if(this.manual_nodename.value.trim() == '') {
msg += 'Node name cannot be empty\n';
}
if(msg != '') {
// alert(msg);
}
this.save_button.disabled = msg != "";
}
getPackName() {
if(this.pack_list.selectedIndex == 0) {
return this.manual_packname.value.trim();
}
return this.pack_list.value.trim();
}
getNodeName() {
if(this.manual_nodename.value.trim() != '') {
return this.manual_nodename.value.trim();
}
return getPureName(this.target_node);
}
createAuthorModeCheck() {
let check = $el("input",{type:'checkbox', id:"author-mode"},[])
const check_label = $el("label",{for:"author-mode"},["Enable author mode"]);
check_label.style.color = "var(--fg-color)";
check_label.style.cursor = "pointer";
check.checked = false;
let self = this;
check.onchange = () => {
self.version_string.disabled = !check.checked;
if(!check.checked) {
self.version_string.value = self.default_ver;
}
else {
alert('If you are not the author, it is not recommended to change the version, as it may cause component update issues.');
}
};
return [check, check_label];
}
createNodeLabel() {
let label = $el('p');
label.className = 'cb-node-label';
if(this.target_node.comfyClass.includes('::'))
label.textContent = getPureName(this.target_node);
else
label.textContent = " _::" + getPureName(this.target_node);
return label;
}
createLabeledInput(placeholder, label, value) {
let textbox = $el('input.cb-widget-input', {type:'text', placeholder:placeholder, value:value}, []);
let self = this;
textbox.onchange = () => {
this.validateInput.call(self);
this.node_label.textContent = this.node_prefix.value + "::" + this.manual_nodename.value;
}
let row = $el('span.cb-widget', {}, [ $el('span.cb-widget-input-label', label), textbox]);
return [row, textbox];
}
createPackListCombo() {
let combo = document.createElement("select");
combo.className = "cb-widget";
let default_packname_option = { value: '##manual', text: 'Packname: Manual' };
combo.appendChild($el('option', default_packname_option, []));
for(let name in pack_map) {
combo.appendChild($el('option', { value: name, text: 'Packname: '+ name }, []));
}
let self = this;
combo.onchange = function () {
if(combo.selectedIndex == 0) {
self.manual_packname.disabled = false;
}
else {
self.manual_packname.disabled = true;
}
};
return combo;
}
}
let orig_handleFile = app.handleFile;
function handleFile(file) {
if (file.name?.endsWith(".json") || file.name?.endsWith(".pack")) {
const reader = new FileReader();
reader.onload = async () => {
let is_component = false;
const jsonContent = JSON.parse(reader.result);
for(let name in jsonContent) {
let cand = jsonContent[name];
is_component = cand.datetime && cand.version;
break;
}
if(is_component) {
handle_import_components(jsonContent);
}
else {
orig_handleFile.call(app, file);
}
};
reader.readAsText(file);
return;
}
orig_handleFile.call(app, file);
}
app.handleFile = handleFile;
let current_component_policy = 'workflow';
try {
api.fetchApi('/manager/component/policy')
.then(response => response.text())
.then(data => { current_component_policy = data; });
}
catch {}
function getChangedVersion(groupNodes) {
if(!Object.keys(pack_map).length || !groupNodes)
return null;
let res = {};
for(let component_name in groupNodes) {
let data = groupNodes[component_name];
if(rpack_map[component_name]) {
let v = versionCompare(data.version, rpack_map[component_name].version);
res[component_name] = v;
}
}
return res;
}
const loadGraphData = app.loadGraphData;
app.loadGraphData = async function () {
if(arguments.length == 0)
return await loadGraphData.apply(this, arguments);
let graphData = arguments[0];
let groupNodes = graphData.extra?.groupNodes;
let res = getChangedVersion(groupNodes);
if(res) {
let target_components = null;
switch(current_component_policy) {
case 'higher':
target_components = Object.keys(res).filter(key => res[key] == 1);
break;
case 'mine':
target_components = Object.keys(res);
break;
default:
// do nothing
}
if(target_components) {
for(let i in target_components) {
let component_name = target_components[i];
let component = rpack_map[component_name];
if(component && graphData.extra?.groupNodes) {
graphData.extra.groupNodes[component_name] = component;
}
}
}
}
else {
console.log('Empty components: policy ignored');
}
arguments[0] = graphData;
return await loadGraphData.apply(this, arguments);
};
export function set_component_policy(v) {
current_component_policy = v;
}
let graphToPrompt = app.graphToPrompt;
app.graphToPrompt = async function () {
let p = await graphToPrompt.call(app);
try {
let groupNodes = p.workflow.extra?.groupNodes;
if(groupNodes) {
p.workflow.extra = { ... p.workflow.extra};
// get used group nodes
let used_group_nodes = new Set();
for(let node of p.workflow.nodes) {
if(node.type.startsWith('workflow/')) {
used_group_nodes.add(node.type.substring(9));
}
}
// remove unused group nodes
let new_groupNodes = {};
for (let key in p.workflow.extra.groupNodes) {
if (used_group_nodes.has(key)) {
new_groupNodes[key] = p.workflow.extra.groupNodes[key];
}
}
p.workflow.extra.groupNodes = new_groupNodes;
}
}
catch(e) {
console.log(`Failed to filtering group nodes: ${e}`);
}
return p;
}

1087
js/components-manager.js

File diff suppressed because it is too large Load Diff

320
js/custom-nodes-downloader.js

@ -1,7 +1,7 @@
import { app } from "../../scripts/app.js"; import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js" import { api } from "../../scripts/api.js"
import { ComfyDialog, $el } from "../../scripts/ui.js"; import { ComfyDialog, $el } from "../../scripts/ui.js";
import { install_checked_custom_node, manager_instance, rebootAPI } from "./common.js"; import { install_checked_custom_node, manager_instance, rebootAPI } from "./common.js";
async function getCustomNodes() { async function getCustomNodes() {
@ -93,9 +93,9 @@ export class CustomNodesInstaller extends ComfyDialog {
data = null; data = null;
static ShowMode = { static ShowMode = {
NORMAL: 0, NORMAL: 0,
MISSING_NODES: 1, MISSING_NODES: 1,
UPDATE: 2, UPDATE: 2,
}; };
clear() { clear() {
@ -109,9 +109,6 @@ export class CustomNodesInstaller extends ComfyDialog {
this.manager_dialog = manager_dialog; this.manager_dialog = manager_dialog;
this.search_keyword = ''; this.search_keyword = '';
this.element = $el("div.comfy-modal", { parent: document.body }, []); this.element = $el("div.comfy-modal", { parent: document.body }, []);
this.currentSortProperty = ''; // The property currently being sorted
this.currentSortAscending = true; // The direction of the current sort
} }
startInstall(target) { startInstall(target) {
@ -157,6 +154,7 @@ export class CustomNodesInstaller extends ComfyDialog {
async filter_missing_node(data) { async filter_missing_node(data) {
const mappings = await getCustomnodeMappings(); const mappings = await getCustomnodeMappings();
// build regex->url map // build regex->url map
const regex_to_url = []; const regex_to_url = [];
for (let i in data) { for (let i in data) {
@ -167,17 +165,11 @@ export class CustomNodesInstaller extends ComfyDialog {
} }
// build name->url map // build name->url map
const name_to_urls = {}; const name_to_url = {};
for (const url in mappings) { for (const url in mappings) {
const names = mappings[url]; const names = mappings[url];
for(const name in names[0]) { for(const name in names[0]) {
let v = name_to_urls[names[0][name]]; name_to_url[names[0][name]] = url;
if(v == undefined) {
v = [];
name_to_urls[names[0][name]] = v;
}
v.push(url);
} }
} }
@ -202,11 +194,9 @@ export class CustomNodesInstaller extends ComfyDialog {
continue; continue;
if (!registered_nodes.has(node_type)) { if (!registered_nodes.has(node_type)) {
const urls = name_to_urls[node_type.trim()]; const url = name_to_url[node_type.trim()];
if(urls) if(url)
urls.forEach(url => { missing_nodes.add(url);
missing_nodes.add(url);
});
else { else {
for(let j in regex_to_url) { for(let j in regex_to_url) {
if(regex_to_url[j].regex.test(node_type)) { if(regex_to_url[j].regex.test(node_type)) {
@ -220,7 +210,7 @@ export class CustomNodesInstaller extends ComfyDialog {
let unresolved_nodes = await getUnresolvedNodesInComponent(); let unresolved_nodes = await getUnresolvedNodesInComponent();
for (let i in unresolved_nodes) { for (let i in unresolved_nodes) {
let node_type = unresolved_nodes[i]; let node_type = unresolved_nodes[i];
const url = name_to_urls[node_type]; const url = name_to_url[node_type];
if(url) if(url)
missing_nodes.add(url); missing_nodes.add(url);
} }
@ -370,181 +360,76 @@ export class CustomNodesInstaller extends ComfyDialog {
} }
} }
sortData(property, ascending = true) { async createGrid() {
this.data.sort((a, b) => { var grid = document.createElement('table');
// Check if either value is -1 and handle accordingly grid.setAttribute('id', 'custom-nodes-grid');
if (a[property] === -1) return 1; // Always put a at the end if its value is -1
if (b[property] === -1) return -1; // Always put b at the end if its value is -1
// And be careful here, (-1<'2024-01-01') and (-1>'2024-01-01') are both false! So I handle -1 seperately.
if (a[property] < b[property]) return ascending ? -1 : 1;
if (a[property] > b[property]) return ascending ? 1 : -1;
return 0;
});
}
resetHeaderStyles() {
const headers = ['th_author', 'th_title', 'th_stars', 'th_last_update']; // Add the IDs of all your sortable headers here
headers.forEach(headerId => {
const header = this.element.querySelector(`#${headerId}`);
if (header) {
header.style.backgroundColor = ''; // Reset to default background color
// Add other style resets if necessary
}
});
}
toggleSort(property) {
// If currently sorted by this property, toggle the direction; else, sort ascending
if (this.currentSortProperty === property) {
this.currentSortAscending = !this.currentSortAscending;
} else {
this.currentSortAscending = false;
}
this.currentSortProperty = property;
this.resetHeaderStyles(); // Reset styles of all sortable headers
// Determine the ID of the header based on the property
let headerId = '';
if (property === 'stars') {
headerId = 'th_stars';
} else if (property === 'last_update') {
headerId = 'th_last_update';
} else if (property === 'author') {
headerId = 'th_author';
} else if (property === 'title') {
headerId = 'th_title';
}
// If we have a valid headerId, change its style to indicate it's the active sort column this.grid_rows = {};
if (headerId) {
const activeHeader = this.element.querySelector(`#${headerId}`);
if (activeHeader) {
activeHeader.style.backgroundColor = '#222';
// Slightly brighter. Add other style changes if necessary.
}
}
// Call sortData with the current property and direction
this.sortData(property, this.currentSortAscending);
// Refresh the grid to display sorted data
this.createGrid();
this.apply_searchbox(this.data);
}
async createGrid() {
// Remove existing table if present
var grid = this.element.querySelector('#custom-nodes-grid');
var panel;
let self = this; let self = this;
if (grid) {
grid.querySelector('tbody').remove(); var thead = document.createElement('thead');
panel = grid.parentNode;
} else {
grid = document.createElement('table');
grid.setAttribute('id', 'custom-nodes-grid');
this.grid_rows = {};
var thead = document.createElement('thead');
var headerRow = document.createElement('tr');
thead.style.position = "sticky";
thead.style.top = "0px";
thead.style.borderCollapse = "collapse";
thead.style.tableLayout = "fixed";
var header0 = document.createElement('th');
header0.style.width = "20px";
this.checkbox_all = $el("input",{type:'checkbox', id:'check_all'},[]);
header0.appendChild(this.checkbox_all);
this.checkbox_all.checked = false;
this.checkbox_all.disabled = true;
this.checkbox_all.addEventListener('change', function() { self.check_all.call(self, self.checkbox_all.checked); });
var header1 = document.createElement('th');
header1.innerHTML = '&nbsp;&nbsp;ID&nbsp;&nbsp;';
header1.style.width = "20px";
var header2 = document.createElement('th');
header2.innerHTML = 'Author';
header2.style.width = "150px";
header2.style.cursor = 'pointer';
header2.setAttribute('id', 'th_author');
header2.onclick = () => this.toggleSort('author');
var header3 = document.createElement('th');
header3.innerHTML = 'Name';
header3.style.width = "20%";
header3.style.cursor = 'pointer';
header3.setAttribute('id', 'th_title');
header3.onclick = () => this.toggleSort('title');
var header4 = document.createElement('th');
header4.innerHTML = 'Description';
header4.style.width = "60%";
// header4.classList.add('expandable-column');
var header5 = document.createElement('th');
header5.innerHTML = '&nbsp;&nbsp;&nbsp;★&nbsp;&nbsp;&nbsp;';
header5.style.width = "130px";
header5.setAttribute('id', 'th_stars');
header5.style.cursor = 'pointer';
header5.onclick = () => this.toggleSort('stars');
var header6 = document.createElement('th');
header6.innerHTML = 'Last Update';
header6.style.width = "130px";
header6.setAttribute('id', 'th_last_update');
header6.style.cursor = 'pointer';
header6.onclick = () => this.toggleSort('last_update');
var header7 = document.createElement('th');
header7.innerHTML = 'Install';
header7.style.width = "130px";
header0.style.position = "sticky";
header0.style.top = "0px";
header1.style.position = "sticky";
header1.style.top = "0px";
header2.style.position = "sticky";
header2.style.top = "0px";
header3.style.position = "sticky";
header3.style.top = "0px";
header4.style.position = "sticky";
header4.style.top = "0px";
header5.style.position = "sticky";
header5.style.top = "0px";
header6.style.position = "sticky";
header6.style.top = "0px";
header7.style.position = "sticky";
header7.style.top = "0px";
thead.appendChild(headerRow);
headerRow.appendChild(header0);
headerRow.appendChild(header1);
headerRow.appendChild(header2);
headerRow.appendChild(header3);
headerRow.appendChild(header4);
headerRow.appendChild(header5);
headerRow.appendChild(header6);
headerRow.appendChild(header7);
headerRow.style.backgroundColor = "Black";
headerRow.style.color = "White";
headerRow.style.textAlign = "center";
headerRow.style.width = "100%";
headerRow.style.padding = "0";
grid.appendChild(thead);
panel = document.createElement('div');
panel.style.width = "100%";
panel.appendChild(grid);
this.element.appendChild(panel);
}
var tbody = document.createElement('tbody'); var tbody = document.createElement('tbody');
var headerRow = document.createElement('tr');
thead.style.position = "sticky";
thead.style.top = "0px";
thead.style.borderCollapse = "collapse";
thead.style.tableLayout = "fixed";
var header0 = document.createElement('th');
header0.style.width = "20px";
this.checkbox_all = $el("input",{type:'checkbox', id:'check_all'},[]);
header0.appendChild(this.checkbox_all);
this.checkbox_all.checked = false;
this.checkbox_all.disabled = true;
this.checkbox_all.addEventListener('change', function() { self.check_all.call(self, self.checkbox_all.checked); });
var header1 = document.createElement('th');
header1.innerHTML = '&nbsp;&nbsp;ID&nbsp;&nbsp;';
header1.style.width = "20px";
var header2 = document.createElement('th');
header2.innerHTML = 'Author';
header2.style.width = "150px";
var header3 = document.createElement('th');
header3.innerHTML = 'Name';
header3.style.width = "20%";
var header4 = document.createElement('th');
header4.innerHTML = 'Description';
header4.style.width = "60%";
// header4.classList.add('expandable-column');
var header5 = document.createElement('th');
header5.innerHTML = 'Install';
header5.style.width = "130px";
header0.style.position = "sticky";
header0.style.top = "0px";
header1.style.position = "sticky";
header1.style.top = "0px";
header2.style.position = "sticky";
header2.style.top = "0px";
header3.style.position = "sticky";
header3.style.top = "0px";
header4.style.position = "sticky";
header4.style.top = "0px";
header5.style.position = "sticky";
header5.style.top = "0px";
thead.appendChild(headerRow);
headerRow.appendChild(header0);
headerRow.appendChild(header1);
headerRow.appendChild(header2);
headerRow.appendChild(header3);
headerRow.appendChild(header4);
headerRow.appendChild(header5);
headerRow.style.backgroundColor = "Black";
headerRow.style.color = "White";
headerRow.style.textAlign = "center";
headerRow.style.width = "100%";
headerRow.style.padding = "0";
grid.appendChild(thead);
grid.appendChild(tbody); grid.appendChild(tbody);
if(this.data) if(this.data)
@ -607,37 +492,8 @@ export class CustomNodesInstaller extends ComfyDialog {
} }
var data5 = document.createElement('td'); var data5 = document.createElement('td');
data5.style.maxWidth = "100px";
data5.className = "cm-node-stars"
if(data.stars < 0) {
data5.textContent = 'N/A';
}
else {
data5.textContent = `${data.stars}`;
}
data5.style.whiteSpace = "nowrap";
data5.style.overflow = "hidden";
data5.style.textOverflow = "ellipsis";
data5.style.textAlign = "center"; data5.style.textAlign = "center";
var lastUpdateDate = new Date();
var data6 = document.createElement('td');
data6.style.maxWidth = "100px";
data6.className = "cm-node-last-update";
if(data.last_update < 0) {
data6.textContent = 'N/A';
}
else {
data6.textContent = `${data.last_update}`.split(' ')[0];
}
data6.style.whiteSpace = "nowrap";
data6.style.overflow = "hidden";
data6.style.textOverflow = "ellipsis";
data6.style.textAlign = "center";
var data7 = document.createElement('td');
data7.style.textAlign = "center";
var installBtn = document.createElement('button'); var installBtn = document.createElement('button');
installBtn.className = "cm-btn-install"; installBtn.className = "cm-btn-install";
var installBtn2 = null; var installBtn2 = null;
@ -711,7 +567,6 @@ export class CustomNodesInstaller extends ComfyDialog {
installBtn.style.backgroundColor = 'black'; installBtn.style.backgroundColor = 'black';
installBtn.style.color = 'white'; installBtn.style.color = 'white';
break; break;
default: default:
installBtn.innerHTML = `Try Install`; installBtn.innerHTML = `Try Install`;
installBtn.style.backgroundColor = 'Gray'; installBtn.style.backgroundColor = 'Gray';
@ -725,7 +580,7 @@ export class CustomNodesInstaller extends ComfyDialog {
install_checked_custom_node(self.grid_rows, j, CustomNodesInstaller.instance, 'update'); install_checked_custom_node(self.grid_rows, j, CustomNodesInstaller.instance, 'update');
}); });
data7.appendChild(installBtn2); data5.appendChild(installBtn2);
} }
if(installBtn3 != null) { if(installBtn3 != null) {
@ -734,7 +589,7 @@ export class CustomNodesInstaller extends ComfyDialog {
install_checked_custom_node(self.grid_rows, j, CustomNodesInstaller.instance, 'toggle_active'); install_checked_custom_node(self.grid_rows, j, CustomNodesInstaller.instance, 'toggle_active');
}); });
data7.appendChild(installBtn3); data5.appendChild(installBtn3);
} }
if(installBtn4 != null) { if(installBtn4 != null) {
@ -743,7 +598,7 @@ export class CustomNodesInstaller extends ComfyDialog {
install_checked_custom_node(self.grid_rows, j, CustomNodesInstaller.instance, 'fix'); install_checked_custom_node(self.grid_rows, j, CustomNodesInstaller.instance, 'fix');
}); });
data7.appendChild(installBtn4); data5.appendChild(installBtn4);
} }
installBtn.style.width = "120px"; installBtn.style.width = "120px";
@ -759,7 +614,7 @@ export class CustomNodesInstaller extends ComfyDialog {
}); });
if(!data.author.startsWith('#NOTICE')){ if(!data.author.startsWith('#NOTICE')){
data7.appendChild(installBtn); data5.appendChild(installBtn);
} }
if(data.installed == 'Fail' || data.author.startsWith('#NOTICE')) if(data.installed == 'Fail' || data.author.startsWith('#NOTICE'))
@ -775,8 +630,6 @@ export class CustomNodesInstaller extends ComfyDialog {
dataRow.appendChild(data3); dataRow.appendChild(data3);
dataRow.appendChild(data4); dataRow.appendChild(data4);
dataRow.appendChild(data5); dataRow.appendChild(data5);
dataRow.appendChild(data6);
dataRow.appendChild(data7);
tbody.appendChild(dataRow); tbody.appendChild(dataRow);
let buttons = []; let buttons = [];
@ -793,11 +646,15 @@ export class CustomNodesInstaller extends ComfyDialog {
this.grid_rows[i] = {data:data, buttons:buttons, checkbox:checkbox, control:dataRow}; this.grid_rows[i] = {data:data, buttons:buttons, checkbox:checkbox, control:dataRow};
} }
const panel = document.createElement('div');
panel.style.width = "100%";
panel.appendChild(grid);
function handleResize() { function handleResize() {
const parentHeight = self.element.clientHeight; const parentHeight = self.element.clientHeight;
const gridHeight = parentHeight - 200; const gridHeight = parentHeight - 200;
grid.style.height = gridHeight + "px"; grid.style.height = gridHeight + "px";
} }
window.addEventListener("resize", handleResize); window.addEventListener("resize", handleResize);
@ -808,6 +665,7 @@ export class CustomNodesInstaller extends ComfyDialog {
grid.style.overflowY = "scroll"; grid.style.overflowY = "scroll";
this.element.style.height = "85%"; this.element.style.height = "85%";
this.element.style.width = "80%"; this.element.style.width = "80%";
this.element.appendChild(panel);
handleResize(); handleResize();
} }

5
js/model-downloader.js

@ -1,7 +1,7 @@
import { app } from "../../scripts/app.js"; import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js" import { api } from "../../scripts/api.js"
import { ComfyDialog, $el } from "../../scripts/ui.js"; import { ComfyDialog, $el } from "../../scripts/ui.js";
import { install_checked_custom_node, manager_instance, rebootAPI, show_message } from "./common.js"; import { install_checked_custom_node, manager_instance, rebootAPI } from "./common.js";
async function install_model(target) { async function install_model(target) {
if(ModelInstaller.instance) { if(ModelInstaller.instance) {
@ -20,7 +20,8 @@ async function install_model(target) {
return true; return true;
} }
catch(exception) { catch(exception) {
show_message(`Install failed: ${target.title} / ${exception}`); app.ui.dialog.show(`Install failed: ${target.title} / ${exception}`);
app.ui.dialog.element.style.zIndex = 10010;
return false; return false;
} }
finally { finally {

32
js/snapshot.js

@ -1,33 +1,29 @@
import { app } from "../../scripts/app.js"; import { app } from "../../scripts/app.js";
import { api } from "../../scripts/api.js" import { api } from "../../scripts/api.js"
import { ComfyDialog, $el } from "../../scripts/ui.js"; import { ComfyDialog, $el } from "../../scripts/ui.js";
import { manager_instance, rebootAPI, show_message } from "./common.js"; import { manager_instance, rebootAPI } from "./common.js";
async function restore_snapshot(target) { async function restore_snapshot(target) {
if(SnapshotManager.instance) { if(SnapshotManager.instance) {
try { try {
const response = await api.fetchApi(`/snapshot/restore?target=${target}`, { cache: "no-store" }); const response = await api.fetchApi(`/snapshot/restore?target=${target}`, { cache: "no-store" });
if(response.status == 403) {
show_message('This action is not allowed with this security level configuration.');
return false;
}
if(response.status == 400) { if(response.status == 400) {
show_message(`Restore snapshot failed: ${target.title} / ${exception}`); app.ui.dialog.show(`Restore snapshot failed: ${target.title} / ${exception}`);
app.ui.dialog.element.style.zIndex = 10010;
} }
app.ui.dialog.close(); app.ui.dialog.close();
return true; return true;
} }
catch(exception) { catch(exception) {
show_message(`Restore snapshot failed: ${target.title} / ${exception}`); app.ui.dialog.show(`Restore snapshot failed: ${target.title} / ${exception}`);
app.ui.dialog.element.style.zIndex = 10010;
return false; return false;
} }
finally { finally {
await SnapshotManager.instance.invalidateControl(); await SnapshotManager.instance.invalidateControl();
SnapshotManager.instance.updateMessage("<BR>To apply the snapshot, please <button id='cm-reboot-button2' class='cm-small-button'>RESTART</button> ComfyUI. And refresh browser.", 'cm-reboot-button2'); SnapshotManager.instance.updateMessage("<BR>To apply the snapshot, please <button id='cm-reboot-button' class='cm-small-button'>RESTART</button> ComfyUI. And refresh browser.", 'cm-reboot-button');
} }
} }
} }
@ -36,21 +32,17 @@ async function remove_snapshot(target) {
if(SnapshotManager.instance) { if(SnapshotManager.instance) {
try { try {
const response = await api.fetchApi(`/snapshot/remove?target=${target}`, { cache: "no-store" }); const response = await api.fetchApi(`/snapshot/remove?target=${target}`, { cache: "no-store" });
if(response.status == 403) {
show_message('This action is not allowed with this security level configuration.');
return false;
}
if(response.status == 400) { if(response.status == 400) {
show_message(`Remove snapshot failed: ${target.title} / ${exception}`); app.ui.dialog.show(`Remove snapshot failed: ${target.title} / ${exception}`);
app.ui.dialog.element.style.zIndex = 10010;
} }
app.ui.dialog.close(); app.ui.dialog.close();
return true; return true;
} }
catch(exception) { catch(exception) {
show_message(`Restore snapshot failed: ${target.title} / ${exception}`); app.ui.dialog.show(`Restore snapshot failed: ${target.title} / ${exception}`);
app.ui.dialog.element.style.zIndex = 10010;
return false; return false;
} }
finally { finally {
@ -66,7 +58,8 @@ async function save_current_snapshot() {
return true; return true;
} }
catch(exception) { catch(exception) {
show_message(`Backup snapshot failed: ${exception}`); app.ui.dialog.show(`Backup snapshot failed: ${exception}`);
app.ui.dialog.element.style.zIndex = 10010;
return false; return false;
} }
finally { finally {
@ -276,7 +269,6 @@ export class SnapshotManager extends ComfyDialog {
save_button.onclick = () => { save_current_snapshot(); } save_button.onclick = () => { save_current_snapshot(); }
save_button.style.display = "inline-block"; save_button.style.display = "inline-block";
save_button.style.horizontalAlign = "right"; save_button.style.horizontalAlign = "right";
save_button.style.width = "170px";
this.message_box = $el('div', {id:'custom-download-message'}, [$el('br'), '']); this.message_box = $el('div', {id:'custom-download-message'}, [$el('br'), '']);
this.message_box.style.height = '60px'; this.message_box.style.height = '60px';

819
model-list.json

@ -270,138 +270,6 @@
"filename": "easynegative.safetensors", "filename": "easynegative.safetensors",
"url": "https://civitai.com/api/download/models/9208" "url": "https://civitai.com/api/download/models/9208"
}, },
{
"name": "stabilityai/comfyui_checkpoints/stable_cascade_stage_b.safetensors",
"type": "checkpoints",
"base": "Stable Cascade",
"save_path": "checkpoints/Stable-Cascade",
"description": "[4.55GB] Stable Cascade stage_b checkpoints",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stable_cascade_stage_b.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/comfyui_checkpoints/stable_cascade_stage_b.safetensors"
},
{
"name": "stabilityai/comfyui_checkpoints/stable_cascade_stage_c.safetensors",
"type": "checkpoints",
"base": "Stable Cascade",
"save_path": "checkpoints/Stable-Cascade",
"description": "[9.22GB] Stable Cascade stage_c checkpoints",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stable_cascade_stage_c.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/comfyui_checkpoints/stable_cascade_stage_c.safetensors"
},
{
"name": "stabilityai/Stable Cascade: stage_a.safetensors (VAE)",
"type": "VAE",
"base": "Stable Cascade",
"save_path": "vae/Stable-Cascade",
"description": "[73.7MB] Stable Cascade: stage_a",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stage_a.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/stage_a.safetensors"
},
{
"name": "stabilityai/Stable Cascade: effnet_encoder.safetensors (VAE)",
"type": "VAE",
"base": "Stable Cascade",
"save_path": "vae/Stable-Cascade",
"description": "[81.5MB] Stable Cascade: effnet_encoder.\nVAE encoder for stage_c latent.",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "effnet_encoder.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/effnet_encoder.safetensors"
},
{
"name": "stabilityai/Stable Cascade: stage_b.safetensors (UNET)",
"type": "unet",
"base": "Stable Cascade",
"save_path": "unet/Stable-Cascade",
"description": "[6.25GB] Stable Cascade: stage_b",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stage_b.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/stage_b.safetensors"
},
{
"name": "stabilityai/Stable Cascade: stage_b_bf16.safetensors (UNET)",
"type": "unet",
"base": "Stable Cascade",
"save_path": "unet/Stable-Cascade",
"description": "[3.13GB] Stable Cascade: stage_b/bf16",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stage_b_bf16.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/stage_b_bf16.safetensors"
},
{
"name": "stabilityai/Stable Cascade: stage_b_lite.safetensors (UNET)",
"type": "unet",
"base": "Stable Cascade",
"save_path": "unet/Stable-Cascade",
"description": "[2.8GB] Stable Cascade: stage_b/lite",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stage_b_lite.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/stage_b_lite.safetensors"
},
{
"name": "stabilityai/Stable Cascade: stage_b_lite.safetensors (UNET)",
"type": "unet",
"base": "Stable Cascade",
"save_path": "unet/Stable-Cascade",
"description": "[1.4GB] Stable Cascade: stage_b/bf16,lite",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stage_b_lite_bf16.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/stage_b_lite_bf16.safetensors"
},
{
"name": "stabilityai/Stable Cascade: stage_c.safetensors (UNET)",
"type": "unet",
"base": "Stable Cascade",
"save_path": "unet/Stable-Cascade",
"description": "[14.4GB] Stable Cascade: stage_c",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stage_c.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/stage_c.safetensors"
},
{
"name": "stabilityai/Stable Cascade: stage_c_bf16.safetensors (UNET)",
"type": "unet",
"base": "Stable Cascade",
"save_path": "unet/Stable-Cascade",
"description": "[7.18GB] Stable Cascade: stage_c/bf16",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stage_c_bf16.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/stage_c_bf16.safetensors"
},
{
"name": "stabilityai/Stable Cascade: stage_c_lite.safetensors (UNET)",
"type": "unet",
"base": "Stable Cascade",
"save_path": "unet/Stable-Cascade",
"description": "[4.12GB] Stable Cascade: stage_c/lite",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stage_c_lite.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/stage_c_lite.safetensors"
},
{
"name": "stabilityai/Stable Cascade: stage_c_lite.safetensors (UNET)",
"type": "unet",
"base": "Stable Cascade",
"save_path": "unet/Stable-Cascade",
"description": "[2.06GB] Stable Cascade: stage_c/bf16,lite",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stage_c_lite_bf16.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/stage_c_lite_bf16.safetensors"
},
{
"name": "stabilityai/Stable Cascade: text_encoder (CLIP)",
"type": "clip",
"base": "Stable Cascade",
"save_path": "clip/Stable-Cascade",
"description": "[1.39GB] Stable Cascade: text_encoder",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "model.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/text_encoder/model.safetensors"
},
{ {
"name": "SDXL-Turbo 1.0 (fp16)", "name": "SDXL-Turbo 1.0 (fp16)",
"type": "checkpoints", "type": "checkpoints",
@ -492,39 +360,6 @@
"filename": "sd_xl_offset_example-lora_1.0.safetensors", "filename": "sd_xl_offset_example-lora_1.0.safetensors",
"url": "https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/sd_xl_offset_example-lora_1.0.safetensors" "url": "https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/sd_xl_offset_example-lora_1.0.safetensors"
}, },
{
"name": "SDXL Lightning LoRA (2step)",
"type": "lora",
"base": "SDXL",
"save_path": "loras/SDXL-Lightning",
"description": "SDXL Lightning LoRA (2step)",
"reference": "https://huggingface.co/ByteDance/SDXL-Lightning",
"filename": "sdxl_lightning_2step_lora.safetensors",
"url": "https://huggingface.co/ByteDance/SDXL-Lightning/resolve/main/sdxl_lightning_2step_lora.safetensors"
},
{
"name": "SDXL Lightning LoRA (4step)",
"type": "lora",
"base": "SDXL",
"save_path": "loras/SDXL-Lightning",
"description": "SDXL Lightning LoRA (4step)",
"reference": "https://huggingface.co/ByteDance/SDXL-Lightning",
"filename": "sdxl_lightning_4step_lora.safetensors",
"url": "https://huggingface.co/ByteDance/SDXL-Lightning/resolve/main/sdxl_lightning_4step_lora.safetensors"
},
{
"name": "SDXL Lightning LoRA (8step)",
"type": "lora",
"base": "SDXL",
"save_path": "loras/SDXL-Lightning",
"description": "SDXL Lightning LoRA (8tep)",
"reference": "https://huggingface.co/ByteDance/SDXL-Lightning",
"filename": "sdxl_lightning_8step_lora.safetensors",
"url": "https://huggingface.co/ByteDance/SDXL-Lightning/resolve/main/sdxl_lightning_8step_lora.safetensors"
},
{ {
"name": "v1-5-pruned-emaonly.ckpt", "name": "v1-5-pruned-emaonly.ckpt",
"type": "checkpoints", "type": "checkpoints",
@ -585,6 +420,16 @@
"filename": "AOM3A3_orangemixs.safetensors", "filename": "AOM3A3_orangemixs.safetensors",
"url": "https://huggingface.co/WarriorMama777/OrangeMixs/resolve/main/Models/AbyssOrangeMix3/AOM3A3_orangemixs.safetensors" "url": "https://huggingface.co/WarriorMama777/OrangeMixs/resolve/main/Models/AbyssOrangeMix3/AOM3A3_orangemixs.safetensors"
}, },
{
"name": "Anything v3 (fp16; pruned)",
"type": "checkpoints",
"base": "SD1.5",
"save_path": "default",
"description": "Anything v3 (anime style)",
"reference": "https://huggingface.co/Linaqruf/anything-v3.0",
"filename": "anything-v3-fp16-pruned.safetensors",
"url": "https://huggingface.co/Linaqruf/anything-v3.0/resolve/main/anything-v3-fp16-pruned.safetensors"
},
{ {
"name": "Waifu Diffusion 1.5 Beta3 (fp16)", "name": "Waifu Diffusion 1.5 Beta3 (fp16)",
"type": "checkpoints", "type": "checkpoints",
@ -815,116 +660,6 @@
"filename": "t2iadapter_style_sd14v1.pth", "filename": "t2iadapter_style_sd14v1.pth",
"url": "https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_style_sd14v1.pth" "url": "https://huggingface.co/TencentARC/T2I-Adapter/resolve/main/models/t2iadapter_style_sd14v1.pth"
}, },
{
"name": "T2I-Adapter XL (lineart) FP16",
"type": "T2I-Adapter",
"base": "SDXL 1.0",
"save_path": "default",
"description": "ControlNet T2I-Adapter XL for lineart",
"reference": "https://huggingface.co/TencentARC/t2i-adapter-lineart-sdxl-1.0",
"filename": "t2i-adapter-lineart-sdxl-1.0.fp16.safetensors",
"url": "https://huggingface.co/TencentARC/t2i-adapter-lineart-sdxl-1.0/resolve/main/diffusion_pytorch_model.fp16.safetensors"
},
{
"name": "T2I-Adapter XL (canny) FP16",
"type": "T2I-Adapter",
"base": "SDXL 1.0",
"save_path": "default",
"description": "ControlNet T2I-Adapter XL for canny",
"reference": "https://huggingface.co/TencentARC/t2i-adapter-canny-sdxl-1.0",
"filename": "t2i-adapter-canny-sdxl-1.0.fp16.safetensors",
"url": "https://huggingface.co/TencentARC/t2i-adapter-canny-sdxl-1.0/resolve/main/diffusion_pytorch_model.fp16.safetensors"
},
{
"name": "T2I-Adapter XL (depth-zoe) FP16",
"type": "T2I-Adapter",
"base": "SDXL 1.0",
"save_path": "default",
"description": "ControlNet T2I-Adapter XL for depth-zoe",
"reference": "https://huggingface.co/TencentARC/t2i-adapter-depth-zoe-sdxl-1.0",
"filename": "t2i-adapter-depth-zoe-sdxl-1.0.fp16.safetensors",
"url": "https://huggingface.co/TencentARC/t2i-adapter-depth-zoe-sdxl-1.0/resolve/main/diffusion_pytorch_model.fp16.safetensors"
},
{
"name": "T2I-Adapter XL (depth-midas) FP16",
"type": "T2I-Adapter",
"base": "SDXL 1.0",
"save_path": "default",
"description": "ControlNet T2I-Adapter XL for depth-midas",
"reference": "https://huggingface.co/TencentARC/t2i-adapter-depth-midas-sdxl-1.0",
"filename": "t2i-adapter-depth-midas-sdxl-1.0.fp16.safetensors",
"url": "https://huggingface.co/TencentARC/t2i-adapter-depth-midas-sdxl-1.0/resolve/main/diffusion_pytorch_model.fp16.safetensors"
},
{
"name": "T2I-Adapter XL (sketch) FP16",
"type": "T2I-Adapter",
"base": "SDXL 1.0",
"save_path": "default",
"description": "ControlNet T2I-Adapter XL for sketch",
"reference": "https://huggingface.co/TencentARC/t2i-adapter-sketch-sdxl-1.0",
"filename": "t2i-adapter-sketch-sdxl-1.0.fp16.safetensors",
"url": "https://huggingface.co/TencentARC/t2i-adapter-sketch-sdxl-1.0/resolve/main/diffusion_pytorch_model.fp16.safetensors"
},
{
"name": "T2I-Adapter XL (lineart)",
"type": "T2I-Adapter",
"base": "SDXL 1.0",
"save_path": "default",
"description": "ControlNet T2I-Adapter XL for lineart",
"reference": "https://huggingface.co/TencentARC/t2i-adapter-lineart-sdxl-1.0",
"filename": "t2i-adapter-lineart-sdxl-1.0.safetensors",
"url": "https://huggingface.co/TencentARC/t2i-adapter-lineart-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors"
},
{
"name": "T2I-Adapter XL (canny)",
"type": "T2I-Adapter",
"base": "SDXL 1.0",
"save_path": "default",
"description": "ControlNet T2I-Adapter XL for canny",
"reference": "https://huggingface.co/TencentARC/t2i-adapter-canny-sdxl-1.0",
"filename": "t2i-adapter-canny-sdxl-1.0.safetensors",
"url": "https://huggingface.co/TencentARC/t2i-adapter-canny-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors"
},
{
"name": "T2I-Adapter XL (depth-zoe)",
"type": "T2I-Adapter",
"base": "SDXL 1.0",
"save_path": "default",
"description": "ControlNet T2I-Adapter XL for depth-zoe",
"reference": "https://huggingface.co/TencentARC/t2i-adapter-depth-zoe-sdxl-1.0",
"filename": "t2i-adapter-depth-zoe-sdxl-1.0.safetensors",
"url": "https://huggingface.co/TencentARC/t2i-adapter-depth-zoe-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors"
},
{
"name": "T2I-Adapter XL (depth-midas)",
"type": "T2I-Adapter",
"base": "SDXL 1.0",
"save_path": "default",
"description": "ControlNet T2I-Adapter XL for depth-midas",
"reference": "https://huggingface.co/TencentARC/t2i-adapter-depth-midas-sdxl-1.0",
"filename": "t2i-adapter-depth-midas-sdxl-1.0.safetensors",
"url": "https://huggingface.co/TencentARC/t2i-adapter-depth-midas-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors"
},
{
"name": "T2I-Adapter XL (sketch)",
"type": "T2I-Adapter",
"base": "SDXL 1.0",
"save_path": "default",
"description": "ControlNet T2I-Adapter XL for sketch",
"reference": "https://huggingface.co/TencentARC/t2i-adapter-sketch-sdxl-1.0",
"filename": "t2i-adapter-sketch-sdxl-1.0.safetensors",
"url": "https://huggingface.co/TencentARC/t2i-adapter-sketch-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors"
},
{
"name": "T2I-Adapter XL (openpose)",
"type": "T2I-Adapter",
"base": "SDXL 1.0",
"save_path": "default",
"description": "ControlNet T2I-Adapter XL for openpose",
"reference": "https://huggingface.co/TencentARC/t2i-adapter-openpose-sdxl-1.0",
"filename": "t2i-adapter-openpose-sdxl-1.0.safetensors",
"url": "https://huggingface.co/TencentARC/t2i-adapter-openpose-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors"
},
{ {
"name": "CiaraRowles/TemporalNet2", "name": "CiaraRowles/TemporalNet2",
"type": "controlnet", "type": "controlnet",
@ -1778,24 +1513,24 @@
"url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter_sd15.safetensors" "url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter_sd15.safetensors"
}, },
{ {
"name": "ip-adapter_sd15_light_v11.bin", "name": "ip-adapter_sd15_light.safetensors",
"type": "IP-Adapter", "type": "IP-Adapter",
"base": "SD1.5", "base": "SD1.5",
"save_path": "ipadapter", "save_path": "ipadapter",
"description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.", "description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.",
"reference": "https://huggingface.co/h94/IP-Adapter", "reference": "https://huggingface.co/h94/IP-Adapter",
"filename": "ip-adapter_sd15_light_v11.bin", "filename": "ip-adapter_sd15_light.safetensors",
"url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter_sd15_light_v11.bin" "url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter_sd15_light.safetensors"
}, },
{ {
"name": "ip-adapter_sd15_light.safetensors [DEPRECATED]", "name": "ip-adapter_sd15_vit-G.safetensors",
"type": "IP-Adapter", "type": "IP-Adapter",
"base": "SD1.5", "base": "SD1.5",
"save_path": "ipadapter", "save_path": "ipadapter",
"description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.", "description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.",
"reference": "https://huggingface.co/h94/IP-Adapter", "reference": "https://huggingface.co/h94/IP-Adapter",
"filename": "ip-adapter_sd15_light.safetensors", "filename": "ip-adapter_sd15_vit-G.safetensors",
"url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter_sd15_light.safetensors" "url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter_sd15_vit-G.safetensors"
}, },
{ {
"name": "ip-adapter-plus_sd15.safetensors", "name": "ip-adapter-plus_sd15.safetensors",
@ -1827,16 +1562,6 @@
"filename": "ip-adapter-full-face_sd15.safetensors", "filename": "ip-adapter-full-face_sd15.safetensors",
"url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter-full-face_sd15.safetensors" "url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter-full-face_sd15.safetensors"
}, },
{
"name": "ip-adapter_sd15_vit-G.safetensors",
"type": "IP-Adapter",
"base": "SD1.5",
"save_path": "ipadapter",
"description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.",
"reference": "https://huggingface.co/h94/IP-Adapter",
"filename": "ip-adapter_sd15_vit-G.safetensors",
"url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter_sd15_vit-G.safetensors"
},
{ {
"name": "ip-adapter-faceid_sd15.bin", "name": "ip-adapter-faceid_sd15.bin",
"type": "IP-Adapter", "type": "IP-Adapter",
@ -1848,17 +1573,7 @@
"url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid_sd15.bin" "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid_sd15.bin"
}, },
{ {
"name": "ip-adapter-faceid-plusv2_sd15.bin", "name": "ip-adapter-faceid-plus_sd15.bin",
"type": "IP-Adapter",
"base": "SD1.5",
"save_path": "ipadapter",
"description": "IP-Adapter-FaceID Plus V2 Model (SD1.5) [ipadapter]",
"reference": "https://huggingface.co/h94/IP-Adapter-FaceID",
"filename": "ip-adapter-faceid-plusv2_sd15.bin",
"url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plusv2_sd15.bin"
},
{
"name": "ip-adapter-faceid-plus_sd15.bin [DEPRECATED]",
"type": "IP-Adapter", "type": "IP-Adapter",
"base": "SD1.5", "base": "SD1.5",
"save_path": "ipadapter", "save_path": "ipadapter",
@ -1868,17 +1583,7 @@
"url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plus_sd15.bin" "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plus_sd15.bin"
}, },
{ {
"name": "ip-adapter-faceid-portrait-v11_sd15.bin", "name": "ip-adapter-faceid-portrait_sd15.bin",
"type": "IP-Adapter",
"base": "SD1.5",
"save_path": "ipadapter",
"description": "IP-Adapter-FaceID Portrait V11 Model (SD1.5) [ipadapter]",
"reference": "https://huggingface.co/h94/IP-Adapter-FaceID",
"filename": "ip-adapter-faceid-portrait-v11_sd15.bin",
"url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-portrait-v11_sd15.bin"
},
{
"name": "ip-adapter-faceid-portrait_sd15.bin [DEPRECATED]",
"type": "IP-Adapter", "type": "IP-Adapter",
"base": "SD1.5", "base": "SD1.5",
"save_path": "ipadapter", "save_path": "ipadapter",
@ -1907,26 +1612,6 @@
"filename": "ip-adapter-faceid-plusv2_sdxl.bin", "filename": "ip-adapter-faceid-plusv2_sdxl.bin",
"url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plusv2_sdxl.bin" "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plusv2_sdxl.bin"
}, },
{
"name": "ip-adapter-faceid-portrait_sdxl.bin",
"type": "IP-Adapter",
"base": "SDXL",
"save_path": "ipadapter",
"description": "IP-Adapter-FaceID Portrait Model (SDXL) [ipadapter]",
"reference": "https://huggingface.co/h94/IP-Adapter-FaceID",
"filename": "ip-adapter-faceid-portrait_sdxl.bin",
"url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-portrait_sdxl.bin"
},
{
"name": "ip-adapter-faceid-portrait_sdxl_unnorm.bin",
"type": "IP-Adapter",
"base": "SDXL",
"save_path": "ipadapter",
"description": "IP-Adapter-FaceID Portrait Model (SDXL/unnorm) [ipadapter]",
"reference": "https://huggingface.co/h94/IP-Adapter-FaceID",
"filename": "ip-adapter-faceid-portrait_sdxl_unnorm.bin",
"url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-portrait_sdxl_unnorm.bin"
},
{ {
"name": "ip-adapter-faceid_sd15_lora.safetensors", "name": "ip-adapter-faceid_sd15_lora.safetensors",
"type": "lora", "type": "lora",
@ -1938,7 +1623,7 @@
"url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid_sd15_lora.safetensors" "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid_sd15_lora.safetensors"
}, },
{ {
"name": "ip-adapter-faceid-plus_sd15_lora.safetensors [DEPRECATED]", "name": "ip-adapter-faceid-plus_sd15_lora.safetensors",
"type": "lora", "type": "lora",
"base": "SD1.5", "base": "SD1.5",
"save_path": "loras/ipadapter", "save_path": "loras/ipadapter",
@ -1947,6 +1632,16 @@
"filename": "ip-adapter-faceid-plus_sd15_lora.safetensors", "filename": "ip-adapter-faceid-plus_sd15_lora.safetensors",
"url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plus_sd15_lora.safetensors" "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plus_sd15_lora.safetensors"
}, },
{
"name": "ip-adapter-faceid-plusv2_sd15.bin",
"type": "IP-Adapter",
"base": "SD1.5",
"save_path": "ipadapter",
"description": "IP-Adapter-FaceID-Plus V2 Model (SD1.5) [ipadapter]",
"reference": "https://huggingface.co/h94/IP-Adapter-FaceID",
"filename": "ip-adapter-faceid-plusv2_sd15.bin",
"url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plusv2_sd15.bin"
},
{ {
"name": "ip-adapter-faceid-plusv2_sd15_lora.safetensors", "name": "ip-adapter-faceid-plusv2_sd15_lora.safetensors",
"type": "lora", "type": "lora",
@ -1977,7 +1672,6 @@
"filename": "ip-adapter-faceid-plusv2_sdxl_lora.safetensors", "filename": "ip-adapter-faceid-plusv2_sdxl_lora.safetensors",
"url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plusv2_sdxl_lora.safetensors" "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-plusv2_sdxl_lora.safetensors"
}, },
{ {
"name": "ip-adapter_sdxl.safetensors", "name": "ip-adapter_sdxl.safetensors",
"type": "IP-Adapter", "type": "IP-Adapter",
@ -2019,27 +1713,6 @@
"url": "https://huggingface.co/h94/IP-Adapter/resolve/main/sdxl_models/ip-adapter-plus-face_sdxl_vit-h.safetensors" "url": "https://huggingface.co/h94/IP-Adapter/resolve/main/sdxl_models/ip-adapter-plus-face_sdxl_vit-h.safetensors"
}, },
{
"name": "ip_plus_composition_sd15.safetensors",
"type": "IP-Adapter",
"base": "SD1.5",
"save_path": "ipadapter",
"description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.",
"reference": "https://huggingface.co/ostris/ip-composition-adapter",
"filename": "ip_plus_composition_sd15.safetensors",
"url": "https://huggingface.co/ostris/ip-composition-adapter/resolve/main/ip_plus_composition_sd15.safetensors"
},
{
"name": "ip_plus_composition_sdxl.safetensors",
"type": "IP-Adapter",
"base": "SDXL",
"save_path": "ipadapter",
"description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.",
"reference": "https://huggingface.co/ostris/ip-composition-adapter",
"filename": "ip_plus_composition_sdxl.safetensors",
"url": "https://huggingface.co/ostris/ip-composition-adapter/resolve/main/ip_plus_composition_sdxl.safetensors"
},
{ {
"name": "pfg-novel-n10.pt", "name": "pfg-novel-n10.pt",
"type": "PFG", "type": "PFG",
@ -2209,440 +1882,6 @@
"reference": "https://huggingface.co/InstantX/InstantID", "reference": "https://huggingface.co/InstantX/InstantID",
"filename": "diffusion_pytorch_model.safetensors", "filename": "diffusion_pytorch_model.safetensors",
"url": "https://huggingface.co/InstantX/InstantID/resolve/main/ControlNetModel/diffusion_pytorch_model.safetensors" "url": "https://huggingface.co/InstantX/InstantID/resolve/main/ControlNetModel/diffusion_pytorch_model.safetensors"
},
{
"name": "efficient_sam_s_cpu.jit [ComfyUI-YoloWorld-EfficientSAM]",
"type": "efficient_sam",
"base": "efficient_sam",
"save_path": "custom_nodes/ComfyUI-YoloWorld-EfficientSAM",
"description": "Install efficient_sam_s_cpu.jit into ComfyUI-YoloWorld-EfficientSAM",
"reference": "https://huggingface.co/camenduru/YoloWorld-EfficientSAM/tree/main",
"filename": "efficient_sam_s_cpu.jit",
"url": "https://huggingface.co/camenduru/YoloWorld-EfficientSAM/resolve/main/efficient_sam_s_cpu.jit"
},
{
"name": "efficient_sam_s_gpu.jit [ComfyUI-YoloWorld-EfficientSAM]",
"type": "efficient_sam",
"base": "efficient_sam",
"save_path": "custom_nodes/ComfyUI-YoloWorld-EfficientSAM",
"description": "Install efficient_sam_s_gpu.jit into ComfyUI-YoloWorld-EfficientSAM",
"reference": "https://huggingface.co/camenduru/YoloWorld-EfficientSAM/tree/main",
"filename": "efficient_sam_s_gpu.jit",
"url": "https://huggingface.co/camenduru/YoloWorld-EfficientSAM/resolve/main/efficient_sam_s_gpu.jit"
},
{
"name": "shape_predictor_68_face_landmarks.dat [Face Analysis]",
"type": "Shape Predictor",
"base": "DLIB",
"save_path": "custom_nodes/ComfyUI_FaceAnalysis/dlib",
"description": "To use the Face Analysis for ComfyUI custom node, installation of this model is needed.",
"reference": "https://huggingface.co/matt3ounstable/dlib_predictor_recognition/tree/main",
"filename": "shape_predictor_68_face_landmarks.dat",
"url": "https://huggingface.co/matt3ounstable/dlib_predictor_recognition/resolve/main/shape_predictor_68_face_landmarks.dat"
},
{
"name": "dlib_face_recognition_resnet_model_v1.dat [Face Analysis]",
"type": "Face Recognition",
"base": "DLIB",
"save_path": "custom_nodes/ComfyUI_FaceAnalysis/dlib",
"description": "To use the Face Analysis for ComfyUI custom node, installation of this model is needed.",
"reference": "https://huggingface.co/matt3ounstable/dlib_predictor_recognition/tree/main",
"filename": "dlib_face_recognition_resnet_model_v1.dat",
"url": "https://huggingface.co/matt3ounstable/dlib_predictor_recognition/resolve/main/dlib_face_recognition_resnet_model_v1.dat"
},
{
"name": "InstanceDiffusion/fusers",
"type": "InstanceDiffusion",
"base": "SD1.5",
"save_path": "instance_models/fuser_models",
"description": "Fusers checkpoints for multi-object prompting with InstanceDiffusion.",
"reference": "https://huggingface.co/logtd/instance_diffusion",
"filename": "fusers.ckpt",
"url": "https://huggingface.co/logtd/instance_diffusion/resolve/main/fusers.ckpt"
},
{
"name": "InstanceDiffusion/position_net",
"type": "InstanceDiffusion",
"base": "SD1.5",
"save_path": "instance_models/positionnet_models",
"description": "PositionNet checkpoints for multi-object prompting with InstanceDiffusion.",
"reference": "https://huggingface.co/logtd/instance_diffusion",
"filename": "position_net.ckpt",
"url": "https://huggingface.co/logtd/instance_diffusion/resolve/main/position_net.ckpt"
},
{
"name": "InstanceDiffusion/scaleu",
"type": "InstanceDiffusion",
"base": "SD1.5",
"save_path": "instance_models/scaleu_models",
"description": "ScaleU checkpoints for multi-object prompting with InstanceDiffusion.",
"reference": "https://huggingface.co/logtd/instance_diffusion",
"filename": "scaleu.ckpt",
"url": "https://huggingface.co/logtd/instance_diffusion/resolve/main/scaleu.ckpt"
},
{
"name": "1k3d68.onnx",
"type": "insightface",
"base": "inswapper",
"save_path": "insightface/models/buffalo_l",
"description": "Buffalo_l 1k3d68.onnx model for IpAdapterPlus",
"reference": "https://github.com/cubiq/ComfyUI_IPAdapter_plus?tab=readme-ov-file#faceid",
"filename": "1k3d68.onnx",
"url": "https://huggingface.co/public-data/insightface/resolve/main/models/buffalo_l/1k3d68.onnx"
},
{
"name": "2d106det.onnx",
"type": "insightface",
"base": "inswapper",
"save_path": "insightface/models/buffalo_l",
"description": "Buffalo_l 2d106det.onnx model for IpAdapterPlus",
"reference": "https://github.com/cubiq/ComfyUI_IPAdapter_plus?tab=readme-ov-file#faceid",
"filename": "2d106det.onnx",
"url": "https://huggingface.co/public-data/insightface/resolve/main/models/buffalo_l/2d106det.onnx"
},
{
"name": "det_10g.onnx",
"type": "insightface",
"base": "inswapper",
"save_path": "insightface/models/buffalo_l",
"description": "Buffalo_l det_10g.onnx model for IpAdapterPlus",
"reference": "https://github.com/cubiq/ComfyUI_IPAdapter_plus?tab=readme-ov-file#faceid",
"filename": "det_10g.onnx",
"url": "https://huggingface.co/public-data/insightface/resolve/main/models/buffalo_l/det_10g.onnx"
},
{
"name": "genderage.onnx",
"type": "insightface",
"base": "inswapper",
"save_path": "insightface/models/buffalo_l",
"description": "Buffalo_l genderage.onnx model for IpAdapterPlus",
"reference": "https://github.com/cubiq/ComfyUI_IPAdapter_plus?tab=readme-ov-file#faceid",
"filename": "genderage.onnx",
"url": "https://huggingface.co/public-data/insightface/resolve/main/models/buffalo_l/genderage.onnx"
},
{
"name": "w600k_r50.onnx",
"type": "insightface",
"base": "inswapper",
"save_path": "insightface/models/buffalo_l",
"description": "Buffalo_l w600k_r50.onnx model for IpAdapterPlus",
"reference": "https://github.com/cubiq/ComfyUI_IPAdapter_plus?tab=readme-ov-file#faceid",
"filename": "w600k_r50.onnx",
"url": "https://huggingface.co/public-data/insightface/resolve/main/models/buffalo_l/w600k_r50.onnx"
},
{
"name": "BLIP ImageCaption (COCO) w/ ViT-B and CapFilt-L",
"type": "BLIP_MODEL",
"base": "blip_model",
"save_path": "blip",
"description": "BLIP ImageCaption (COCO) w/ ViT-B and CapFilt-L",
"reference": "https://github.com/salesforce/BLIP",
"filename": "model_base_capfilt_large.pth",
"url": "https://storage.googleapis.com/sfr-vision-language-research/BLIP/models/model_base_capfilt_large.pth"
},
{
"name": "GroundingDINO SwinT OGC - Model",
"type": "GroundingDINO",
"base": "DINO",
"save_path": "groundingdino",
"description": "GroundingDINO SwinT OGC Model",
"reference": "https://huggingface.co/ShilongLiu/GroundingDINO",
"filename": "groundingdino_swint_ogc.pth",
"url": "https://huggingface.co/ShilongLiu/GroundingDINO/resolve/main/groundingdino_swint_ogc.pth"
},
{
"name": "GroundingDINO SwinT OGC - CFG File",
"type": "GroundingDINO",
"base": "DINO",
"save_path": "groundingdino",
"description": "GroundingDINO SwinT OGC CFG File",
"reference": "https://huggingface.co/ShilongLiu/GroundingDINO/resolve/main/GroundingDINO_SwinT_OGC.cfg.py",
"filename": "GroundingDINO_SwinT_OGC.cfg.py",
"url": "https://huggingface.co/ShilongLiu/GroundingDINO/raw/main/GroundingDINO_SwinT_OGC.cfg.py"
},
{
"name": "ViT-H SAM model",
"type": "sam",
"base": "SAM",
"save_path": "sams",
"description": "Segmenty Anything SAM model (ViT-H)",
"reference": "https://github.com/facebookresearch/segment-anything#model-checkpoints",
"filename": "sam_vit_h_4b8939.pth",
"url": "https://dl.fbaipublicfiles.com/segment_anything/sam_vit_h_4b8939.pth"
},
{
"name": "ViT-L SAM model",
"type": "sam",
"base": "SAM",
"save_path": "sams",
"description": "Segmenty Anything SAM model (ViT-L)",
"reference": "https://github.com/facebookresearch/segment-anything#model-checkpoints",
"filename": "sam_vit_l_0b3195.pth",
"url": "https://dl.fbaipublicfiles.com/segment_anything/sam_vit_l_0b3195.pth"
},
{
"name": "MobileSAM",
"type": "sam",
"base": "SAM",
"save_path": "sams",
"description": "MobileSAM",
"reference": "https://github.com/ChaoningZhang/MobileSAM/",
"filename": "mobile_sam.pt",
"url": "https://github.com/ChaoningZhang/MobileSAM/blob/master/weights/mobile_sam.pt"
},
{
"name": "DynamiCrafter 1024 bf16 safetensors",
"type": "checkpoints",
"base": "DynamiCrafter",
"save_path": "checkpoints/dynamicrafter",
"description": "DynamiCrafter image2video model 1024x575",
"reference": "https://huggingface.co/Kijai/DynamiCrafter_pruned/",
"filename": "dynamicrafter_1024_v1_bf16.safetensors",
"url": "https://huggingface.co/Kijai/DynamiCrafter_pruned/resolve/main/dynamicrafter_1024_v1_bf16.safetensors"
},
{
"name": "DynamiCrafter 512 interpolation bf16 safetensors",
"type": "checkpoints",
"base": "DynamiCrafter",
"save_path": "checkpoints/dynamicrafter",
"description": "DynamiCrafter image2video interpolation model 512",
"reference": "https://huggingface.co/Kijai/DynamiCrafter_pruned/",
"filename": "dynamicrafter_512_interp_v1_bf16.safetensors",
"url": "https://huggingface.co/Kijai/DynamiCrafter_pruned/resolve/main/dynamicrafter_512_interp_v1_bf16.safetensors"
},
{
"name": "monster-labs - Controlnet QR Code Monster v1 For SDXL",
"type": "controlnet",
"base": "SDXL",
"save_path": "default",
"description": "monster-labs - Controlnet QR Code Monster v1 For SDXL",
"reference": "https://huggingface.co/monster-labs/control_v1p_sdxl_qrcode_monster",
"filename": "control_v1p_sdxl_qrcode_monster.safetensors",
"url": "https://huggingface.co/monster-labs/control_v1p_sdxl_qrcode_monster/resolve/main/diffusion_pytorch_model.safetensors"
},
{
"name": "Depth-FM-v1 fp16 safetensors",
"type": "checkpoints",
"base": "Depth-FM",
"save_path": "checkpoints/depthfm",
"description": "Depth-FM monocular depth estimation model",
"reference": "https://huggingface.co/Kijai/depth-fm-pruned",
"filename": "depthfm-v1_fp16.safetensors",
"url": "https://huggingface.co/Kijai/depth-fm-pruned/resolve/main/depthfm-v1_fp16.safetensors"
},
{
"name": "Depth-FM-v1 fp32 safetensors",
"type": "checkpoints",
"base": "Depth-FM",
"save_path": "checkpoints/depthfm",
"description": "Depth-FM monocular depth estimation model",
"reference": "https://huggingface.co/Kijai/depth-fm-pruned",
"filename": "depthfm-v1_fp32.safetensors",
"url": "https://huggingface.co/Kijai/depth-fm-pruned/resolve/main/depthfm-v1_fp32.safetensors"
},
{
"name": "SUPIR-v0F.ckpt",
"type": "checkpoints",
"base": "SUPIR",
"save_path": "checkpoints/SUPIR",
"description": "SUPIR checkpoint model",
"reference": "https://huggingface.co/camenduru/SUPIR/tree/main",
"filename": "SUPIR-v0F.ckpt",
"url": "https://huggingface.co/camenduru/SUPIR/resolve/main/SUPIR-v0F.ckpt"
},
{
"name": "SUPIR-v0Q.ckpt",
"type": "checkpoints",
"base": "SUPIR",
"save_path": "checkpoints/SUPIR",
"description": "SUPIR checkpoint model",
"reference": "https://huggingface.co/camenduru/SUPIR/tree/main",
"filename": "SUPIR-v0Q.ckpt",
"url": "https://huggingface.co/camenduru/SUPIR/resolve/main/SUPIR-v0Q.ckpt"
},
{
"name": "Kijai/SUPIR-v0F_fp16.safetensors (pruned)",
"type": "checkpoints",
"base": "SUPIR",
"save_path": "checkpoints/SUPIR",
"description": "SUPIR checkpoint model",
"reference": "https://huggingface.co/Kijai/SUPIR_pruned/tree/main",
"filename": "SUPIR-v0F_fp16.safetensors",
"url": "https://huggingface.co/Kijai/SUPIR_pruned/resolve/main/SUPIR-v0F_fp16.safetensors"
},
{
"name": "Kijai/SUPIR-v0Q_fp16.safetensors (pruned)",
"type": "checkpoints",
"base": "SUPIR",
"save_path": "checkpoints/SUPIR",
"description": "SUPIR checkpoint model",
"reference": "https://huggingface.co/Kijai/SUPIR_pruned/tree/main",
"filename": "SUPIR-v0Q_fp16.safetensors",
"url": "https://huggingface.co/Kijai/SUPIR_pruned/resolve/main/SUPIR-v0Q_fp16.safetensors"
},
{
"name": "RAM",
"type": "RAM",
"base": "RAM",
"save_path": "rams",
"description": "RAM Recognize Anything Model",
"reference": "https://huggingface.co/xinyu1205/recognize_anything_model",
"filename": "ram_swin_large_14m.pth",
"url": "https://huggingface.co/xinyu1205/recognize_anything_model/resolve/main/ram_swin_large_14m.pth"
},
{
"name": "RAM++",
"type": "RAM",
"base": "RAM",
"save_path": "rams",
"description": "RAM++ Recognize Anything Model",
"reference": "https://huggingface.co/xinyu1205/recognize-anything-plus-model",
"filename": "ram_plus_swin_large_14m.pth",
"url": "https://huggingface.co/xinyu1205/recognize-anything-plus-model/resolve/main/ram_plus_swin_large_14m.pth"
},
{
"name": "tag2text",
"type": "RAM",
"base": "RAM",
"save_path": "rams",
"description": "tag2text Recognize Anything Model",
"reference": "https://huggingface.co/xinyu1205/recognize_anything_model",
"filename": "tag2text_swin_14m.pth",
"url": "https://huggingface.co/xinyu1205/recognize_anything_model/resolve/main/tag2text_swin_14m.pth"
},
{
"name": "Zero123 3D object Model",
"type": "Zero123",
"base": "Zero123",
"save_path": "checkpoints/zero123",
"description": "model that been trained on 10M+ 3D objects from Objaverse-XL, used for generated rotated CamView",
"reference": "https://objaverse.allenai.org/docs/zero123-xl/",
"filename": "zero123-xl.ckpt",
"url": "https://huggingface.co/kealiu/zero123-xl/resolve/main/zero123-xl.ckpt"
},
{
"name": "Zero123 3D object Model",
"type": "Zero123",
"base": "Zero123",
"save_path": "checkpoints/zero123",
"description": "Stable Zero123 is a model for view-conditioned image generation based on [a/Zero123](https://github.com/cvlab-columbia/zero123).",
"reference": "https://huggingface.co/stabilityai/stable-zero123",
"filename": "stable_zero123.ckpt",
"url": "https://huggingface.co/stabilityai/stable-zero123/resolve/main/stable_zero123.ckpt"
},
{
"name": "Zero123 3D object Model",
"type": "Zero123",
"base": "Zero123",
"save_path": "checkpoints/zero123",
"description": "Zero123 original checkpoints in 105000 steps.",
"reference": "https://huggingface.co/cvlab/zero123-weights",
"filename": "zero123-105000.ckpt",
"url": "https://huggingface.co/cvlab/zero123-weights/resolve/main/105000.ckpt"
},
{
"name": "Zero123 3D object Model",
"type": "Zero123",
"base": "Zero123",
"save_path": "checkpoints/zero123",
"description": "Zero123 original checkpoints in 165000 steps.",
"reference": "https://huggingface.co/cvlab/zero123-weights",
"filename": "zero123-165000.ckpt",
"url": "https://huggingface.co/cvlab/zero123-weights/resolve/main/165000.ckpt"
},
{
"name": "InstantID/ip-adapter",
"type": "instantid",
"base": "SDXL",
"save_path": "instantid/SDXL",
"description": "ip-adapter model for cubiq/InstantID",
"reference": "https://huggingface.co/InstantX/InstantID",
"filename": "ip-adapter.bin",
"url": "https://huggingface.co/InstantX/InstantID/resolve/main/ip-adapter.bin"
},
{
"name": "InstantID/ControlNet",
"type": "controlnet",
"base": "SDXL",
"save_path": "controlnet/SDXL/instantid",
"description": "instantid controlnet model for cubiq/InstantID",
"reference": "https://huggingface.co/InstantX/InstantID",
"filename": "diffusion_pytorch_model.safetensors",
"url": "https://huggingface.co/InstantX/InstantID/resolve/main/ControlNetModel/diffusion_pytorch_model.safetensors"
},
{
"name": "MonsterMMORPG/insightface (for InstantID)",
"type": "insightface",
"base": "SDXL",
"save_path": "insightface/models",
"description": "MonsterMMORPG insightface model for cubiq/InstantID",
"reference": "https://huggingface.co/MonsterMMORPG/tools/tree/main",
"filename": "antelopev2.zip",
"url": "https://huggingface.co/MonsterMMORPG/tools/resolve/main/antelopev2.zip"
},
{
"name": "IC-Light/fc",
"type": "IC-Light",
"base": "SD1.5",
"save_path": "unet/IC-Light",
"description": "The default relighting model, conditioned on text and foreground",
"reference": "https://huggingface.co/lllyasviel/ic-light",
"filename": "iclight_sd15_fc.safetensors",
"url": "https://huggingface.co/lllyasviel/ic-light/resolve/main/iclight_sd15_fc.safetensors"
},
{
"name": "IC-Light/fbc",
"type": "IC-Light",
"base": "SD1.5",
"save_path": "unet/IC-Light",
"description": "Relighting model conditioned with text, foreground, and background",
"reference": "https://huggingface.co/lllyasviel/ic-light",
"filename": "iclight_sd15_fbc.safetensors",
"url": "https://huggingface.co/lllyasviel/ic-light/resolve/main/iclight_sd15_fbc.safetensors"
},
{
"name": "IC-Light/fcon",
"type": "IC-Light",
"base": "SD1.5",
"save_path": "unet/IC-Light",
"description": "Same as iclight_sd15_fc.safetensors, but trained with offset noise",
"reference": "https://huggingface.co/lllyasviel/ic-light",
"filename": "iclight_sd15_fcon.safetensors",
"url": "https://huggingface.co/lllyasviel/ic-light/resolve/main/iclight_sd15_fcon.safetensors"
},
{
"name": "ID-Animator/animator.ckpt",
"type": "ID-Animator",
"base": "SD1.5",
"save_path": "custom_nodes/ComfyUI_ID_Animator/models",
"description": "ID-Animator checkpoint",
"reference": "https://huggingface.co/spaces/ID-Animator/ID-Animator",
"filename": "animator.ckpt",
"url": "https://huggingface.co/spaces/ID-Animator/ID-Animator/resolve/main/animator.ckpt"
},
{
"name": "ID-Animator/mm_sd_v15_v2.ckpt",
"type": "ID-Animator",
"base": "SD1.5",
"save_path": "custom_nodes/ComfyUI_ID_Animator/models/animatediff_models",
"description": "AnimateDiff checkpoint for ID-Animator",
"reference": "https://huggingface.co/spaces/ID-Animator/ID-Animator",
"filename": "mm_sd_v15_v2.ckpt",
"url": "https://huggingface.co/spaces/ID-Animator/ID-Animator/resolve/main/mm_sd_v15_v2.ckpt"
},
{
"name": "ID-Animator/image_encoder",
"type": "ID-Animator",
"base": "SD1.5",
"save_path": "custom_nodes/ComfyUI_ID_Animator/models/image_encoder",
"description": "CLIP Image encoder for ID-Animator",
"reference": "https://huggingface.co/spaces/ID-Animator/ID-Animator",
"filename": "model.safetensors",
"url": "https://huggingface.co/spaces/ID-Animator/ID-Animator/resolve/main/image_encoder/model.safetensors"
} }
] ]
} }

656
node_db/dev/custom-node-list.json

@ -10,631 +10,35 @@
}, },
{
"author": "Quasimondo",
"title": "ComfyUI-QuasimondoNodes [WIP]",
"id": "quasimondo-nodes",
"reference": "https://github.com/Quasimondo/ComfyUI-QuasimondoNodes",
"files": [
"https://github.com/Quasimondo/ComfyUI-QuasimondoNodes"
],
"install_type": "git-clone",
"description": "Nodes:Custom Shader, Spring Mesh"
},
{
"author": "TSFSean",
"title": "ComfyUI-TSFNodes",
"id": "tsfnodes",
"reference": "https://github.com/TSFSean/ComfyUI-TSFNodes",
"files": [
"https://github.com/TSFSean/ComfyUI-TSFNodes"
],
"install_type": "git-clone",
"description": "Nodes:GyroOSC"
},
{
"author": "blib-la",
"title": "ComfyUI-Captain-Extensions",
"id": "captain",
"reference": "https://github.com/blib-la/ComfyUI-Captain-Extensions",
"files": [
"https://github.com/blib-la/ComfyUI-Captain-Extensions"
],
"install_type": "git-clone",
"description": "ComfyUI extensions for better [a/Captain](https://github.com/blib-la/captain) integration."
},
{
"author": "ejektaflex",
"title": "ComfyUI-Ty",
"reference": "https://github.com/ejektaflex/ComfyUI-Ty",
"files": [
"https://github.com/ejektaflex/ComfyUI-Ty"
],
"install_type": "git-clone",
"description": "Nodes:Lora Block Weight Regex Loader"
},
{
"author": "88IO",
"title": "ComfyUI Image Reordering Plugins [WIP]",
"reference": "https://github.com/88IO/ComfyUI-ImageReorder",
"files": [
"https://github.com/88IO/ComfyUI-ImageReorder"
],
"install_type": "git-clone",
"description": "A custom node reorder multiple image frames based on indexes or curves."
},
{
"author": "christian-byrne",
"title": "Python Interpreter ComfyUI Node [UNSAFE]",
"reference": "https://github.com/christian-byrne/python-interpreter-node",
"files": [
"https://github.com/christian-byrne/python-interpreter-node"
],
"install_type": "git-clone",
"description": "For debugging, parsing data, generating random values, converting types, testing custom nodes faster.\nReference and use variables in the code using the same names as the inputs in the UI\nWrapper class around tensors with operator overloading for doing common image manipulation tasks.I might remove this aspect\n[w/This extension allows you to run programs through Python code in your workflow, which may not be secure. Use with caution.]"
},
{
"author": "sofakid",
"title": "dandy [UNSAFE]",
"reference": "https://github.com/sofakid/dandy",
"files": [
"https://github.com/sofakid/dandy"
],
"install_type": "git-clone",
"description": "Dandy is a JavaScript bridge for ComfyUI. It includes everything you need to make JavaScript enabled extensions, or just load and code in little editor nodes right in ComfyUI.[w/This code can cause security issues because it allows for the execution of arbitrary JavaScript input.]"
},
{
"author": "tachyon-beep",
"title": "comfyui-simplefeed [UNSAFE]",
"reference": "https://github.com/tachyon-beep/comfyui-simplefeed",
"files": [
"https://github.com/tachyon-beep/comfyui-simplefeed"
],
"install_type": "git-clone",
"description": "A simple image feed for comfyUI which is easily configurable and easily extensible.\nUse the filter button to select which nodes write to the feed. Under settings, there are options that allow you: Position the feed. Set a max iamge count for the feed. Set oldest to newest or newest to oldest."
},
{
"author": "liusida",
"title": "ComfyUI-Sida-Remove-Image [UNSAFE]",
"reference": "https://github.com/liusida/ComfyUI-Sida-Remove-Image",
"files": [
"https://github.com/liusida/ComfyUI-Sida-Remove-Image"
],
"install_type": "git-clone",
"description": "Nodes: LoadImageWithPrivacy, RemoveImage.[w/This extension is not secure because it provides the capability to delete files from arbitrary paths.]"
},
{ {
"author": "shadowcz007", "author": "shadowcz007",
"title": "ComfyUI-PuLID [TEST]", "title": "comfyui-musicgen",
"reference": "https://github.com/shadowcz007/ComfyUI-PuLID-Test", "reference": "https://github.com/shadowcz007/comfyui-musicgen",
"files": [
"https://github.com/shadowcz007/ComfyUI-PuLID-Test"
],
"install_type": "git-clone",
"description": "[a/PuLID](https://github.com/ToTheBeginning/PuLID) ComfyUI native implementation."
},
{
"author": "sangeet",
"title": "comfyui-testui [TEST]",
"reference": "https://github.com/sangeet/comfyui-testui",
"files": [
"https://github.com/sangeet/comfyui-testui"
],
"install_type": "git-clone",
"description": "Simple Frontend For ComfyUI workflow"
},
{
"author": "Elawphant",
"title": "ComfyUI-MusicGen [WIP]",
"id": "musicgen",
"reference": "https://github.com/Elawphant/ComfyUI-MusicGen",
"files": [
"https://github.com/Elawphant/ComfyUI-MusicGen"
],
"install_type": "git-clone",
"description": "ComfyUI for Meta MusicGen."
},
{
"author": "jtscmw01",
"title": "ComfyUI-DiffBIR",
"id": "diffbir",
"reference": "https://github.com/jtscmw01/ComfyUI-DiffBIR",
"files": [
"https://github.com/jtscmw01/ComfyUI-DiffBIR"
],
"install_type": "git-clone",
"description": "This extension provides [a/DiffBIR](https://github.com/XPixelGroup/DiffBIR) feature."
},
{
"author": "Levy1417",
"title": "Universal-Data-Processing-Kit [UNSAFE]",
"reference": "https://github.com/Levy1417/Universal-Data-Processing-Kit",
"files": [
"https://github.com/Levy1417/Universal-Data-Processing-Kit"
],
"install_type": "git-clone",
"description": "Nodes:DPK - Any Eval, DPK - Extract Array, DPK - Run External Program, DPK - Any Literals, DPK - Set Node States, DPK - Realtime Text Preview, DPK - Dynamic Action, DPK - Object To Json, DPK - Json To Object\n[w/This extension includes the ability to execute arbitrary code and programs.]"
},
{
"author": "runtime44",
"title": "Runtime44 ComfyUI Nodes",
"reference": "https://github.com/runtime44/comfyui_r44_nodes",
"files": [
"https://github.com/runtime44/comfyui_r44_nodes"
],
"install_type": "git-clone",
"description": "Nodes: Runtime44Upscaler, Runtime44ColorMatch, Runtime44DynamicKSampler, Runtime44ImageOverlay, Runtime44ImageResizer, Runtime44ImageToNoise, Runtime44MaskSampler, Runtime44TiledMaskSampler, Runtime44IterativeUpscaleFactor, Runtime44ImageEnhance"
},
{
"author": "ericbeyer",
"title": "guidance_interval",
"reference": "https://github.com/ericbeyer/guidance_interval",
"files": [
"https://github.com/ericbeyer/guidance_interval"
],
"install_type": "git-clone",
"description": "Nodes:Guidance Interval\nNOTE: Because the sampling function is replaced, you must restart after executing this custom node to restore the original state."
},
{
"author": "GraftingRayman",
"title": "ComfyUI-GR",
"reference": "https://github.com/GraftingRayman/ComfyUI_GR_PromptSelector",
"files": [
"https://github.com/GraftingRayman/ComfyUI_GR_PromptSelector"
],
"install_type": "git-clone",
"description": "Nodes:GR Prompt Selector"
},
{
"author": "oztrkoguz",
"title": "Kosmos2_BBox_Cutter Models",
"reference": "https://github.com/oztrkoguz/ComfyUI_Kosmos2_BBox_Cutter",
"files": [
"https://github.com/oztrkoguz/ComfyUI_Kosmos2_BBox_Cutter"
],
"install_type": "git-clone",
"description": "Nodes:KosmosLoader, Kosmos2SamplerSimple, Write"
},
{
"author": "ZHO-ZHO-ZHO",
"title": "ComfyUI-PuLID-ZHO [WIP]",
"reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-PuLID-ZHO",
"files": [
"https://github.com/ZHO-ZHO-ZHO/ComfyUI-PuLID-ZHO"
],
"install_type": "git-clone",
"description": "Unofficial implementation of [a/PuLID](https://github.com/ToTheBeginning/PuLID)(diffusers) for ComfyUI"
},
{
"author": "longgui0318",
"title": "comfyui-one-more-step [WIP]",
"reference": "https://github.com/longgui0318/comfyui-one-more-step",
"files": [
"https://github.com/longgui0318/comfyui-one-more-step"
],
"install_type": "git-clone",
"description": "[a/(OMS)mhh0318/OneMoreStep](https://github.com/mhh0318/OneMoreStep) comfyui support ."
},
{
"author": "unknown",
"title": "CLIPTextEncodeAndEnhancev4 (shirazdesigner)",
"reference": "https://github.com/shirazdesigner/CLIPTextEncodeAndEnhancev4",
"files": [
"https://github.com/shirazdesigner/CLIPTextEncodeAndEnhancev4"
],
"install_type": "git-clone",
"description": "Nodes:CLIPTextEncodeAndEnhance.\nNOTE:Translation:This is a wrapper that simply makes it easy to install an existing node via git."
},
{
"author": "umisetokikaze",
"title": "comfyui_mergekit [WIP]",
"reference": "https://github.com/umisetokikaze/comfyui_mergekit",
"files": [
"https://github.com/umisetokikaze/comfyui_mergekit"
],
"install_type": "git-clone",
"description": "Nodes:DefineSaveName, SetModels, get_skip, LoadLR, LoadTarget, SetTokenizer, Merge, SetLayer, SetModels"
},
{
"author": "Video3DGenResearch",
"title": "ComfyUI Batch Input Node",
"reference": "https://github.com/Video3DGenResearch/comfyui-batch-input-node",
"files": [
"https://github.com/Video3DGenResearch/comfyui-batch-input-node"
],
"install_type": "git-clone",
"description": "Nodes:BatchInputText"
},
{
"author": "kijai",
"title": "ComfyUI nodes to use DeepSeek-VL",
"reference": "https://github.com/kijai/ComfyUI-DeepSeek-VL",
"files": [
"https://github.com/kijai/ComfyUI-DeepSeek-VL"
],
"install_type": "git-clone",
"description": "[a/https://huggingface.co/deepseek-ai](https://huggingface.co/deepseek-ai)"
},
{
"author": "GentlemanHu",
"title": "ComfyUI-Notifier",
"reference": "https://github.com/GentlemanHu/ComfyUI-Notifier",
"files": [
"https://github.com/GentlemanHu/ComfyUI-Notifier"
],
"install_type": "git-clone",
"description": "Nodes:GentlemanHu_Notifier"
},
{
"author": "nat-chan",
"title": "comfyui-in-memory-transceiver",
"reference": "https://github.com/nat-chan/comfyui-in-memory-transceiver",
"files": [
"https://github.com/nat-chan/comfyui-in-memory-transceiver"
],
"install_type": "git-clone",
"description": "Why? When processing a large number of requests, the SaveImage and LoadImage nodes may be IO-limited, and using shared memory improves performance by passing images only through memory access, not through IO."
},
{
"author": "DrMWeigand",
"title": "ComfyUI_LineBreakInserter",
"reference": "https://github.com/DrMWeigand/ComfyUI_LineBreakInserter",
"files": [
"https://github.com/DrMWeigand/ComfyUI_LineBreakInserter"
],
"install_type": "git-clone",
"description": "Nodes:Line Break Inserter"
},
{
"author": "WilliamStanford",
"title": "visuallabs_comfyui_nodes",
"reference": "https://github.com/WilliamStanford/visuallabs_comfyui_nodes",
"files": [
"https://github.com/WilliamStanford/visuallabs_comfyui_nodes"
],
"install_type": "git-clone",
"description": "Nodes:PointStringFromFloatArray"
},
{
"author": "bruce007lee",
"title": "comfyui-cleaner",
"reference": "https://github.com/bruce007lee/comfyui-cleaner",
"files": [
"https://github.com/bruce007lee/comfyui-cleaner"
],
"install_type": "git-clone",
"description": "Nodes:cleaner"
},
{
"author": "ExponentialML",
"title": "ComfyUI_LiveDirector (WIP)",
"reference": "https://github.com/ExponentialML/ComfyUI_LiveDirector",
"files": [
"https://github.com/ExponentialML/ComfyUI_LiveDirector"
],
"install_type": "git-clone",
"description": "Experimental method to use reference video to drive motion in generations without training in ComfyUI."
},
{
"author": "logtd",
"title": "ComfyUI-MotionThiefExperiment",
"reference": "https://github.com/logtd/ComfyUI-MotionThiefExperiment",
"files": [
"https://github.com/logtd/ComfyUI-MotionThiefExperiment"
],
"install_type": "git-clone",
"description": "Nodes:This is an experimental node pack to test using reference videos for their motion.\nIt isn't compatible with a lot of things as this is a hacky implementation for experiments only."
},
{
"author": "hy134300",
"title": "comfyui-hb-node",
"reference": "https://github.com/hy134300/comfyui-hb-node",
"files": [
"https://github.com/hy134300/comfyui-hb-node"
],
"install_type": "git-clone",
"description": "Nodes:sound voice, text concat, latent to list, movie generate, movie batch, hy save image, generate story"
},
{
"author": "gameltb",
"title": "io_comfyui",
"reference": "https://github.com/gameltb/io_comfyui",
"files": [
"https://github.com/gameltb/io_comfyui"
],
"install_type": "git-clone",
"description": "Let Blender work with ComfyUI by ComfyScript. This addon is still in development."
},
{
"author": "ALatentPlace",
"title": "YANC- Yet Another Node Collection",
"reference": "https://github.com/ALatentPlace/ComfyUI_yanc",
"files": [
"https://github.com/ALatentPlace/ComfyUI_yanc"
],
"install_type": "git-clone",
"description": "This is another node collection for ComfyUI. It includes some basic nodes that I find useful, and I've also created them to meet my personal needs."
},
{
"author": "Jiffies-64",
"title": "ComfyUI-SaveImagePlus",
"reference": "https://github.com/Jiffies-64/ComfyUI-SaveImagePlus",
"files": [
"https://github.com/Jiffies-64/ComfyUI-SaveImagePlus"
],
"install_type": "git-clone",
"description": "Nodes:SaveImagePlus"
},
{
"author": "kadirnar",
"title": "ComfyUI-Adapter [WIP]",
"reference": "https://github.com/kadirnar/ComfyUI-Adapter",
"files": [
"https://github.com/kadirnar/ComfyUI-Adapter"
],
"install_type": "git-clone",
"description": "WIP"
},
{
"author": "Beinsezii",
"title": "comfyui-amd-go-fast",
"reference": "https://github.com/Beinsezii/comfyui-amd-go-fast",
"files": [
"https://github.com/Beinsezii/comfyui-amd-go-fast"
],
"install_type": "git-clone",
"description": "This contains all-in-one 'principled' nodes for T2I, I2I, refining, and scaling. Additionally it has many tools for directly manipulating the color of latents, high res fix math, and scripted image post-processing."
},
{
"author": "sugarkwork",
"title": "comfyui_psd [WIP]",
"reference": "https://github.com/sugarkwork/comfyui_psd",
"files": [
"https://github.com/sugarkwork/comfyui_psd"
],
"install_type": "git-clone",
"description": "Not working yet."
},
{
"author": "SadaleNet",
"title": "ComfyUI Port for Google's Prompt-to-Prompt",
"reference": "https://github.com/SadaleNet/ComfyUI-Prompt-To-Prompt",
"files": [
"https://github.com/SadaleNet/ComfyUI-Prompt-To-Prompt"
],
"install_type": "git-clone",
"description": "This is a PoC port of [a/Google's Prompt-to-Prompt](https://github.com/google/prompt-to-prompt/) to ComfyUI. It isn't feature complete. But it's good enough for evaluating if prompt-to-prompt is of any good."
},
{
"author": "MushroomFleet",
"title": "DJZ-Nodes",
"reference": "https://github.com/MushroomFleet/DJZ-Nodes",
"files": [
"https://github.com/MushroomFleet/DJZ-Nodes"
],
"install_type": "git-clone",
"description": "Nodes:Aspect Size. Drift Johnsons Custom nodes for ComfyUI"
},
{
"author": "stavsap",
"title": "ComfyUI Ollama [WIP]",
"reference": "https://github.com/stavsap/ComfyUI-React-SDK",
"files": [
"https://github.com/stavsap/ComfyUI-React-SDK"
],
"install_type": "git-clone",
"description": "This project is for building React application as an overlay upon ComfyUI.\nProviding and ability to provide desired UI with ComfyUI API and workflows.\nInspired by: [a/https://github.com/cubiq/Comfy_Dungeon](https://github.com/cubiq/Comfy_Dungeon)"
},
{
"author": "chaojie",
"title": "ComfyUI DynamiCrafter",
"reference": "https://github.com/chaojie/ComfyUI-DynamiCrafter",
"files": [
"https://github.com/chaojie/ComfyUI-DynamiCrafter"
],
"install_type": "git-clone",
"description": "ComfyUI [a/DynamiCrafter](https://github.com/Doubiiu/DynamiCrafter)"
},
{
"author": "cubiq",
"title": "Comfy Dungeon [WIP]",
"reference": "https://github.com/cubiq/Comfy_Dungeon",
"files": [
"https://github.com/cubiq/Comfy_Dungeon"
],
"install_type": "git-clone",
"description": "Build D&D Character Portraits with ComfyUI.\nIMPORTANT: At the moment this is mostly a tech demo to show how to build a web app on top of ComfyUI. The code is very messy and the application doesn't guaratee consistent results."
},
{
"author": "dfl",
"title": "comfyui-stylegan",
"reference": "https://github.com/dfl/comfyui-stylegan",
"files": [
"https://github.com/dfl/comfyui-stylegan"
],
"install_type": "git-clone",
"description": "Generator for StyleGAN 3"
},
{
"author": "christian-byrne",
"title": "elimination-nodes",
"reference": "https://github.com/christian-byrne/elimination-nodes",
"files": [
"https://github.com/christian-byrne/elimination-nodes"
],
"install_type": "git-clone",
"description": "Nodes:Paste Cutout on Base Image"
},
{
"author": "A719689614",
"title": "ComfyUI_AC_FUNV8Beta1",
"reference": "https://github.com/A719689614/ComfyUI_AC_FUNV8Beta1",
"files": [
"https://github.com/A719689614/ComfyUI_AC_FUNV8Beta1"
],
"install_type": "git-clone",
"description": "Nodes:AC_Super_Controlnet/Checkpoint/Loras/Lora&LCM/KSampler/UpKSampler/SaveImage/PreviewImage/CKPT&LCM/CLIPEN/EmptLatent, AC_FUN_SUPER_LARGE, AC_Super_Come_Ckpt, AC_Super_Come_Lora"
},
{
"author": "houdinii",
"title": "comfy-magick [WIP]",
"reference": "https://github.com/houdinii/comfy-magick",
"files": [
"https://github.com/houdinii/comfy-magick"
],
"install_type": "git-clone",
"description": "This is a way to implement ImageMagick functionality in ComfyUI, which is generally PIL (pillow) based. I'm not sure the best way to handle this, as batch images make it a lot more complex, but the general idea will be two nodes to translate the IMAGE type, a torch.tensor of shape [batch, height, width, channels], or [1, 600, 800, 3] for a single 800x600 image, into/from a wand Image object."
},
{
"author": "tjorbogarden",
"title": "my-useful-comfyui-custom-nodes",
"reference": "https://github.com/tjorbogarden/my-useful-comfyui-custom-nodes",
"files": [
"https://github.com/tjorbogarden/my-useful-comfyui-custom-nodes"
],
"install_type": "git-clone",
"description": "Nodes:My-Image Sizer, KSamplerSDXLAdvanced."
},
{
"author": "DeTK",
"title": "ComfyUI Node Switcher",
"reference": "https://github.com/DeTK/ComfyUI-Switch",
"files": [
"https://github.com/DeTK/ComfyUI-Switch"
],
"install_type": "git-clone",
"description": "Nodes:NodeSwitch."
},
{
"author": "GrindHouse66",
"title": "GH Tools for ComfyUI",
"reference": "https://github.com/GrindHouse66/ComfyUI-GH_Tools",
"files": [
"https://github.com/GrindHouse66/ComfyUI-GH_Tools"
],
"install_type": "git-clone",
"description": "Nodes:GH Tools Image Sizer, GH Tools Simple Scale. Simple quality of life Tools for ComfyUI. Basically, If it makes my life easier, it will be here. The list will grow over time."
},
{
"author": "sdfxai",
"title": "SDFXBridgeForComfyUI - ComfyUI Custom Node for SDFX Integration",
"reference": "https://github.com/sdfxai/SDFXBridgeForComfyUI",
"files": [
"https://github.com/sdfxai/SDFXBridgeForComfyUI"
],
"install_type": "git-clone",
"description": "SDFXBridgeForComfyUI is a custom node designed for seamless integration between ComfyUI and the SDFX solution. This custom node allows users to make ComfyUI compatible with SDFX when running the ComfyUI instance on their local machines."
},
{
"author": "Beinsezii",
"title": "comfyui-amd-go-fast",
"reference": "https://github.com/Beinsezii/comfyui-amd-go-fast",
"files": [
"https://github.com/Beinsezii/comfyui-amd-go-fast"
],
"install_type": "git-clone",
"description": "See details: [a/link](https://github.com/Beinsezii/comfyui-amd-go-fast?tab=readme-ov-file)"
},
{
"author": "SeedV",
"title": "ComfyUI-SeedV-Nodes [UNSAFE]",
"reference": "https://github.com/SeedV/ComfyUI-SeedV-Nodes",
"files": [
"https://github.com/SeedV/ComfyUI-SeedV-Nodes"
],
"install_type": "git-clone",
"description": "Nodes:Script.\n[w/This extension poses a risk of executing arbitrary commands through workflow execution. Please be cautious.]"
},
{
"author": "mut-ex",
"title": "ComfyUI GLIGEN GUI Node",
"reference": "https://github.com/mut-ex/comfyui-gligengui-node",
"files": [
"https://github.com/mut-ex/comfyui-gligengui-node"
],
"install_type": "git-clone",
"description": "This is a simple, straightforward ComfyUI node to be used along with the [a/GLIGEN GUI](https://github.com/mut-ex/gligen-gui) I developed.\nNOTE:[a/Make sure you have the GLIGEN GUI up and running](https://github.com/mut-ex/gligen-gui/tree/main)"
},
{
"author": "unanan",
"title": "ComfyUI-Dist [WIP]",
"reference": "https://github.com/unanan/ComfyUI-Dist",
"files": [
"https://github.com/unanan/ComfyUI-Dist"
],
"install_type": "git-clone",
"description": "For distributed processing ComfyUI workflows within a local area network.\nNot Finished Yet."
},
{
"author": "NicholasKao1029",
"title": "comfyui-hook",
"reference": "https://github.com/NicholasKao1029/comfyui-hook",
"files": [ "files": [
"https://github.com/NicholasKao1029/comfyui-hook" "https://github.com/shadowcz007/comfyui-musicgen"
], ],
"install_type": "git-clone", "install_type": "git-clone",
"description": "This extension provides additional API" "description": "Nodes:Musicgen"
}, },
{ {
"author": "Extraltodeus", "author": "Extraltodeus",
"title": "Conditioning-token-experiments-for-ComfyUI", "title": "ComfyUI-variableCFGandAntiBurn [WIP]",
"reference": "https://github.com/Extraltodeus/Conditioning-token-experiments-for-ComfyUI", "reference": "https://github.com/Extraltodeus/ComfyUI-variableCFGandAntiBurn",
"files": [
"https://github.com/Extraltodeus/Conditioning-token-experiments-for-ComfyUI"
],
"install_type": "git-clone",
"description": "I made these nodes for experimenting so it's far from perfect but at least it is entertaining!\nIt uses cosine similarities or smallest euclidean distances to find the closest tokens."
},
{
"author": "shadowcz007",
"title": "comfyui-llamafile [WIP]",
"reference": "https://github.com/shadowcz007/comfyui-llamafile",
"files": [ "files": [
"https://github.com/shadowcz007/comfyui-llamafile" "https://github.com/Extraltodeus/ComfyUI-variableCFGandAntiBurn"
], ],
"install_type": "git-clone", "install_type": "git-clone",
"description": "This node is an experimental node aimed at exploring the collaborative way of human-machine creation." "description": "Nodes:Continuous CFG rescaler (pre CFG), Intermediary latent merge (post CFG), Intensity/Brightness limiter (post CFG), Dynamic renoising (post CFG), Automatic CFG scale (pre/post CFG), CFG multiplier per channel (pre CFG), Self-Attention Guidance delayed activation mod (post CFG)"
}, },
{ {
"author": "gameltb", "author": "kijai",
"title": "ComfyUI paper playground", "title": "ComfyUI-ADMotionDirector [WIP]",
"reference": "https://github.com/gameltb/ComfyUI_paper_playground", "reference": "https://github.com/kijai/ComfyUI-ADMotionDirector",
"files": [
"https://github.com/gameltb/ComfyUI_paper_playground"
],
"install_type": "git-clone",
"description": "Evaluate some papers in ComfyUI, just playground.\nNOTE: Various models need to be installed, so please visit the repository to check."
},
{
"author": "huizhang0110",
"title": "ComfyUI_Easy_Nodes_hui",
"reference": "https://github.com/huizhang0110/ComfyUI_Easy_Nodes_hui",
"files": [
"https://github.com/huizhang0110/ComfyUI_Easy_Nodes_hui"
],
"install_type": "git-clone",
"description": "Nodes:EasyEmptyLatentImage"
},
{
"author": "tuckerdarby",
"title": "ComfyUI-TDNodes [WIP]",
"reference": "https://github.com/tuckerdarby/ComfyUI-TDNodes",
"files": [
"https://github.com/tuckerdarby/ComfyUI-TDNodes"
],
"install_type": "git-clone",
"description": "Nodes:KSampler (RAVE), KSampler (TF), Object Tracker, KSampler Batched, Video Tracker Prompt, TemporalNet Preprocessor, Instance Tracker Prompt, Instance Diffusion Loader, Hand Tracker Node"
},
{
"author": "shadowcz007",
"title": "comfyui-musicgen",
"reference": "https://github.com/shadowcz007/comfyui-musicgen",
"files": [ "files": [
"https://github.com/shadowcz007/comfyui-musicgen" "https://github.com/kijai/ComfyUI-ADMotionDirector"
], ],
"install_type": "git-clone", "install_type": "git-clone",
"description": "Nodes:Musicgen" "description": "ComfyUI custom nodes for using [a/AnimateDiff-MotionDirector](https://github.com/ExponentialML/AnimateDiff-MotionDirector)\nAfter training, the LoRAs are intended to be used with the ComfyUI Extension [a/ComfyUI-AnimateDiff-Evolved](https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved)."
}, },
{ {
"author": "shadowcz007", "author": "shadowcz007",
@ -656,6 +60,16 @@
"install_type": "git-clone", "install_type": "git-clone",
"description": "ComfyUI implementation for [a/AnimateLCM](https://animatelcm.github.io/) [[a/paper](https://arxiv.org/abs/2402.00769)].\b[w/This extension includes a large number of nodes imported from the existing custom nodes, increasing the likelihood of conflicts.]" "description": "ComfyUI implementation for [a/AnimateLCM](https://animatelcm.github.io/) [[a/paper](https://arxiv.org/abs/2402.00769)].\b[w/This extension includes a large number of nodes imported from the existing custom nodes, increasing the likelihood of conflicts.]"
}, },
{
"author": "ZHO-ZHO-ZHO",
"title": "ComfyUI-BRIA_AI-RMBG",
"reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-BRIA_AI-RMBG",
"files": [
"https://github.com/ZHO-ZHO-ZHO/ComfyUI-BRIA_AI-RMBG"
],
"install_type": "git-clone",
"description": "Unofficial [a/BRIA Background Removal v1.4](https://huggingface.co/briaai/RMBG-1.4) of BRIA RMBG Model for ComfyUI"
},
{ {
"author": "stutya", "author": "stutya",
"title": "ComfyUI-Terminal [UNSAFE]", "title": "ComfyUI-Terminal [UNSAFE]",
@ -686,6 +100,16 @@
"install_type": "git-clone", "install_type": "git-clone",
"description": "A simple node to request ChatGPT completions. [w/Do not share your workflows including the API key! I'll take no responsibility for your leaked keys.]" "description": "A simple node to request ChatGPT completions. [w/Do not share your workflows including the API key! I'll take no responsibility for your leaked keys.]"
}, },
{
"author": "blepping",
"title": "ComfyUI-sonar (WIP)",
"reference": "https://github.com/blepping/ComfyUI-sonar",
"files": [
"https://github.com/blepping/ComfyUI-sonar"
],
"install_type": "git-clone",
"description": "Extremely WIP and untested implementation of Sonar sampling. Currently it may not be even close to working properly. Only supports Euler and Euler Ancestral sampling. See [a/stable-diffusion-webui-sonar](https://github.com/Kahsolt/stable-diffusion-webui-sonar) for a more in-depth explanation."
},
{ {
"author": "kappa54m", "author": "kappa54m",
"title": "ComfyUI_Usability (WIP)", "title": "ComfyUI_Usability (WIP)",
@ -786,6 +210,16 @@
"install_type": "git-clone", "install_type": "git-clone",
"description": "I was looking for a node to put in place to ensure my prompt etc where going as expected before the rest of the flow executed. To end the session, I just return the input image as None (see expected error). Recommend using it alongside PreviewImage, then output to the rest of the flow and Save Image." "description": "I was looking for a node to put in place to ensure my prompt etc where going as expected before the rest of the flow executed. To end the session, I just return the input image as None (see expected error). Recommend using it alongside PreviewImage, then output to the rest of the flow and Save Image."
}, },
{
"author": "11cafe",
"title": "11cafe/ComfyUI Model Manager [WIP]",
"reference": "https://github.com/11cafe/model-manager-comfyui",
"files": [
"https://github.com/11cafe/model-manager-comfyui"
],
"install_type": "git-clone",
"description": "This answers the itch for being able to easily paste [a/CivitAI.com](CivitAI.com) generated data (or other simple metadata) into Comfy in a way that makes it easy to test with multiple checkpoints."
},
{ {
"author": "birnam", "author": "birnam",
"title": "Gen Data Tester [WIP]", "title": "Gen Data Tester [WIP]",
@ -794,11 +228,11 @@
"https://github.com/birnam/ComfyUI-GenData-Pack" "https://github.com/birnam/ComfyUI-GenData-Pack"
], ],
"install_type": "git-clone", "install_type": "git-clone",
"description": "This answers the itch for being able to easily paste [a/CivitAI.com](https://civitai.com/) generated data (or other simple metadata) into Comfy in a way that makes it easy to test with multiple checkpoints." "description": "This answers the itch for being able to easily paste [a/CivitAI.com](CivitAI.com) generated data (or other simple metadata) into Comfy in a way that makes it easy to test with multiple checkpoints."
}, },
{ {
"author": "ZHO-ZHO-ZHO", "author": "ZHO-ZHO-ZHO",
"title": "ComfyUI-AnyText [WIP]", "title": "ComfyUI-AnyText(WIP)",
"reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-AnyText", "reference": "https://github.com/ZHO-ZHO-ZHO/ComfyUI-AnyText",
"files": [ "files": [
"https://github.com/ZHO-ZHO-ZHO/ComfyUI-AnyText" "https://github.com/ZHO-ZHO-ZHO/ComfyUI-AnyText"

537
node_db/dev/extension-node-map.json

@ -146,49 +146,6 @@
"title_aux": "ComfyUI_Fooocus" "title_aux": "ComfyUI_Fooocus"
} }
], ],
"https://github.com/A719689614/ComfyUI_AC_FUNV8Beta1": [
[
"\u2b1b(TODO)AC_Super_Come_Ckpt",
"\u2b1c(TODO)AC_Super_Come_Lora",
"\u2b55AC_FUN_SUPER_LARGE",
"\ud83c\ude35AC_Super_Checkpoint",
"\ud83c\ude35AC_Super_Loras",
"\ud83c\udfabAC_Super_PreviewImage",
"\ud83c\udfb0AC_Super_Controlnet",
"\ud83d\udcb6AC_Super_EmptLatent",
"\ud83d\udcbcAC_Super_Lora&LCM",
"\ud83d\udcbeAC_Super_SaveImage",
"\ud83d\udcc4AC_Super_CLIPEN",
"\ud83d\udcc8AC_Super_UpKSampler",
"\ud83d\udcdfAC_Super_CKPT&LCM",
"\ud83d\ude80AC_Super_KSampler"
],
{
"title_aux": "ComfyUI_AC_FUNV8Beta1"
}
],
"https://github.com/ALatentPlace/ComfyUI_yanc": [
[
"> Clear Text",
"> Float to Int",
"> Int",
"> Int to Text",
"> Load Image",
"> Load Image From Folder",
"> Resolution by Aspect Ratio",
"> Rotate Image",
"> Save Image",
"> Scale Image to Side",
"> Text",
"> Text Combine",
"> Text Pick Random Line",
"> Text Random Weights",
"> Text Replace"
],
{
"title_aux": "YANC- Yet Another Node Collection"
}
],
"https://github.com/BadCafeCode/execution-inversion-demo-comfyui": [ "https://github.com/BadCafeCode/execution-inversion-demo-comfyui": [
[ [
"AccumulateNode", "AccumulateNode",
@ -264,64 +221,6 @@
"title_aux": "ComfyUI_bd_customNodes" "title_aux": "ComfyUI_bd_customNodes"
} }
], ],
"https://github.com/DeTK/ComfyUI-Switch": [
[
"NodeSwitch"
],
{
"title_aux": "ComfyUI Node Switcher"
}
],
"https://github.com/DrMWeigand/ComfyUI_LineBreakInserter": [
[
"LineBreakInserter"
],
{
"title_aux": "ComfyUI_LineBreakInserter"
}
],
"https://github.com/ExponentialML/ComfyUI_LiveDirector": [
[
"LiveDirector"
],
{
"title_aux": "ComfyUI_LiveDirector (WIP)"
}
],
"https://github.com/Extraltodeus/Conditioning-token-experiments-for-ComfyUI": [
[
"Automatic wildcards",
"Conditioning (Cosine similarities)",
"Conditioning (Maximum absolute)",
"Conditioning (Maximum absolute) text inputs",
"Conditioning (Scale by absolute sum)",
"Conditioning merge clip g/l",
"Conditioning similar tokens recombine",
"Conditioning to text",
"Quick and dirty text encode",
"encode_all_tokens_SDXL"
],
{
"title_aux": "Conditioning-token-experiments-for-ComfyUI"
}
],
"https://github.com/GentlemanHu/ComfyUI-Notifier": [
[
"GentlemanHu_Notifier"
],
{
"title_aux": "ComfyUI-Notifier"
}
],
"https://github.com/GrindHouse66/ComfyUI-GH_Tools": [
[
"GHImg_Sizer",
"GHSimple_Scale"
],
{
"title_aux": "GH Tools for ComfyUI"
}
],
"https://github.com/IvanZhd/comfyui-codeformer": [ "https://github.com/IvanZhd/comfyui-codeformer": [
[ [
"RedBeanie_CustomImageInverter" "RedBeanie_CustomImageInverter"
@ -338,14 +237,6 @@
"title_aux": "comfyui-terminal-command [UNSAFE]" "title_aux": "comfyui-terminal-command [UNSAFE]"
} }
], ],
"https://github.com/Jiffies-64/ComfyUI-SaveImagePlus": [
[
"SaveImagePlus"
],
{
"title_aux": "ComfyUI-SaveImagePlus"
}
],
"https://github.com/Jordach/comfy-consistency-vae": [ "https://github.com/Jordach/comfy-consistency-vae": [
[ [
"Comfy_ConsistencyVAE" "Comfy_ConsistencyVAE"
@ -362,14 +253,6 @@
"title_aux": "ComfyUI-ModelUnloader" "title_aux": "ComfyUI-ModelUnloader"
} }
], ],
"https://github.com/LotzF/ComfyUI-Simple-Chat-GPT-completion": [
[
"ChatGPTCompletion"
],
{
"title_aux": "ComfyUI simple ChatGPT completion [UNSAFE]"
}
],
"https://github.com/MrAdamBlack/CheckProgress": [ "https://github.com/MrAdamBlack/CheckProgress": [
[ [
"CHECK_PROGRESS" "CHECK_PROGRESS"
@ -378,14 +261,6 @@
"title_aux": "CheckProgress [WIP]" "title_aux": "CheckProgress [WIP]"
} }
], ],
"https://github.com/MushroomFleet/DJZ-Nodes": [
[
"AspectSize"
],
{
"title_aux": "DJZ-Nodes"
}
],
"https://github.com/PluMaZero/ComfyUI-SpaceFlower": [ "https://github.com/PluMaZero/ComfyUI-SpaceFlower": [
[ [
"SpaceFlower_HangulPrompt", "SpaceFlower_HangulPrompt",
@ -395,17 +270,6 @@
"title_aux": "ComfyUI-SpaceFlower" "title_aux": "ComfyUI-SpaceFlower"
} }
], ],
"https://github.com/SadaleNet/ComfyUI-Prompt-To-Prompt": [
[
"CLIPTextEncodePromptToPrompt",
"KSamplerPromptToPrompt",
"KSamplerPromptToPromptAttentionMapLogger",
"LocalBlendLayerPresetPromptToPrompt"
],
{
"title_aux": "ComfyUI Port for Google's Prompt-to-Prompt"
}
],
"https://github.com/Sai-ComfyUI/ComfyUI-MS-Nodes": [ "https://github.com/Sai-ComfyUI/ComfyUI-MS-Nodes": [
[ [
"FloatMath", "FloatMath",
@ -421,25 +285,6 @@
"title_aux": "ComfyUI-MS-Nodes [WIP]" "title_aux": "ComfyUI-MS-Nodes [WIP]"
} }
], ],
"https://github.com/SeedV/ComfyUI-SeedV-Nodes": [
[
"CheckpointLoaderSimpleShared //SeedV",
"Script"
],
{
"title_aux": "ComfyUI-SeedV-Nodes [UNSAFE]"
}
],
"https://github.com/Video3DGenResearch/comfyui-batch-input-node": [
[
"BatchImageAndPrompt",
"BatchInputCSV",
"BatchInputText"
],
{
"title_aux": "ComfyUI Batch Input Node"
}
],
"https://github.com/WSJUSA/Comfyui-StableSR": [ "https://github.com/WSJUSA/Comfyui-StableSR": [
[ [
"ColorFix", "ColorFix",
@ -453,23 +298,12 @@
"title_aux": "pre-comfyui-stablsr" "title_aux": "pre-comfyui-stablsr"
} }
], ],
"https://github.com/WilliamStanford/visuallabs_comfyui_nodes": [
[
"CreateFadeMaskAdvancedVL",
"PointStringFromFloatArray",
"RescaleFloatArray",
"StringFromFloatArray"
],
{
"title_aux": "visuallabs_comfyui_nodes"
}
],
"https://github.com/ZHO-ZHO-ZHO/ComfyUI-AnyText": [ "https://github.com/ZHO-ZHO-ZHO/ComfyUI-AnyText": [
[ [
"AnyTextNode_Zho" "AnyTextNode_Zho"
], ],
{ {
"title_aux": "ComfyUI-AnyText [WIP]" "title_aux": "ComfyUI-AnyText\uff08WIP\uff09"
} }
], ],
"https://github.com/alt-key-project/comfyui-dream-video-batches": [ "https://github.com/alt-key-project/comfyui-dream-video-batches": [
@ -519,30 +353,14 @@
"Checkpoint Selector Stacker \ud83d\udc69\u200d\ud83d\udcbb", "Checkpoint Selector Stacker \ud83d\udc69\u200d\ud83d\udcbb",
"Checkpoint Selector \ud83d\udc69\u200d\ud83d\udcbb", "Checkpoint Selector \ud83d\udc69\u200d\ud83d\udcbb",
"Checkpoint to String \ud83d\udc69\u200d\ud83d\udcbb", "Checkpoint to String \ud83d\udc69\u200d\ud83d\udcbb",
"Crop Recombine \ud83d\udc69\u200d\ud83d\udcbb",
"Crop|IP|Inpaint \ud83d\udc69\u200d\ud83d\udcbb",
"Crop|IP|Inpaint|SDXL \ud83d\udc69\u200d\ud83d\udcbb",
"Decode GenData \ud83d\udc69\u200d\ud83d\udcbb", "Decode GenData \ud83d\udc69\u200d\ud83d\udcbb",
"Encode GenData \ud83d\udc69\u200d\ud83d\udcbb", "Encode GenData \ud83d\udc69\u200d\ud83d\udcbb",
"GenData Stacker \ud83d\udc69\u200d\ud83d\udcbb", "GenData Stacker \ud83d\udc69\u200d\ud83d\udcbb",
"IPAdapterApply",
"IPAdapterApplyEncoded",
"IPAdapterApplyFaceID",
"IPAdapterBatchEmbeds",
"IPAdapterEncoder",
"IPAdapterLoadEmbeds",
"IPAdapterModelLoader",
"IPAdapterSaveEmbeds",
"IPAdapterTilesMasked",
"InsightFaceLoader",
"LoRA Stack to String \ud83d\udc69\u200d\ud83d\udcbb", "LoRA Stack to String \ud83d\udc69\u200d\ud83d\udcbb",
"LoRA Stacker From Prompt \ud83d\udc69\u200d\ud83d\udcbb", "LoRA Stacker From Prompt \ud83d\udc69\u200d\ud83d\udcbb",
"Load Checkpoints From File \ud83d\udc69\u200d\ud83d\udcbb", "Load Checkpoints From File \ud83d\udc69\u200d\ud83d\udcbb",
"Load GenData From Dir \ud83d\udc69\u200d\ud83d\udcbb", "Load GenData From Dir \ud83d\udc69\u200d\ud83d\udcbb",
"Parse GenData \ud83d\udc69\u200d\ud83d\udcbb", "Parse GenData \ud83d\udc69\u200d\ud83d\udcbb",
"PrepImageForClipVision",
"PrepImageForInsightFace",
"Provide GenData \ud83d\udc69\u200d\ud83d\udcbb",
"Save Image From GenData \ud83d\udc69\u200d\ud83d\udcbb", "Save Image From GenData \ud83d\udc69\u200d\ud83d\udcbb",
"VAE From String \ud83d\udc69\u200d\ud83d\udcbb", "VAE From String \ud83d\udc69\u200d\ud83d\udcbb",
"VAE to String \ud83d\udc69\u200d\ud83d\udcbb", "VAE to String \ud83d\udc69\u200d\ud83d\udcbb",
@ -552,41 +370,23 @@
"title_aux": "Gen Data Tester [WIP]" "title_aux": "Gen Data Tester [WIP]"
} }
], ],
"https://github.com/bruce007lee/comfyui-cleaner": [ "https://github.com/blepping/ComfyUI-sonar": [
[
"cleaner"
],
{
"title_aux": "comfyui-cleaner"
}
],
"https://github.com/chaojie/ComfyUI-DynamiCrafter": [
[ [
"DynamiCrafter Simple", "SamplerSonarEuler",
"DynamiCrafterInterp Simple", "SamplerSonarEulerA"
"DynamiCrafterInterpLoader",
"DynamiCrafterLoader"
], ],
{ {
"title_aux": "ComfyUI DynamiCrafter" "title_aux": "ComfyUI-sonar (WIP)"
} }
], ],
"https://github.com/comfyanonymous/ComfyUI": [ "https://github.com/comfyanonymous/ComfyUI": [
[ [
"AddNoise",
"AlignYourStepsScheduler",
"BasicGuider",
"BasicScheduler", "BasicScheduler",
"CFGGuider",
"CLIPAttentionMultiply",
"CLIPLoader", "CLIPLoader",
"CLIPMergeAdd",
"CLIPMergeSimple", "CLIPMergeSimple",
"CLIPMergeSubtract",
"CLIPSave", "CLIPSave",
"CLIPSetLastLayer", "CLIPSetLastLayer",
"CLIPTextEncode", "CLIPTextEncode",
"CLIPTextEncodeControlnet",
"CLIPTextEncodeSDXL", "CLIPTextEncodeSDXL",
"CLIPTextEncodeSDXLRefiner", "CLIPTextEncodeSDXLRefiner",
"CLIPVisionEncode", "CLIPVisionEncode",
@ -609,10 +409,7 @@
"ControlNetLoader", "ControlNetLoader",
"CropMask", "CropMask",
"DiffControlNetLoader", "DiffControlNetLoader",
"DifferentialDiffusion",
"DiffusersLoader", "DiffusersLoader",
"DisableNoise",
"DualCFGGuider",
"DualCLIPLoader", "DualCLIPLoader",
"EmptyImage", "EmptyImage",
"EmptyLatentImage", "EmptyLatentImage",
@ -632,7 +429,6 @@
"ImageColorToMask", "ImageColorToMask",
"ImageCompositeMasked", "ImageCompositeMasked",
"ImageCrop", "ImageCrop",
"ImageFromBatch",
"ImageInvert", "ImageInvert",
"ImageOnlyCheckpointLoader", "ImageOnlyCheckpointLoader",
"ImageOnlyCheckpointSave", "ImageOnlyCheckpointSave",
@ -645,7 +441,6 @@
"ImageToMask", "ImageToMask",
"ImageUpscaleWithModel", "ImageUpscaleWithModel",
"InpaintModelConditioning", "InpaintModelConditioning",
"InstructPixToPixConditioning",
"InvertMask", "InvertMask",
"JoinImageWithAlpha", "JoinImageWithAlpha",
"KSampler", "KSampler",
@ -676,25 +471,17 @@
"MaskToImage", "MaskToImage",
"ModelMergeAdd", "ModelMergeAdd",
"ModelMergeBlocks", "ModelMergeBlocks",
"ModelMergeSD1",
"ModelMergeSD2",
"ModelMergeSDXL",
"ModelMergeSimple", "ModelMergeSimple",
"ModelMergeSubtract", "ModelMergeSubtract",
"ModelSamplingContinuousEDM", "ModelSamplingContinuousEDM",
"ModelSamplingDiscrete", "ModelSamplingDiscrete",
"ModelSamplingStableCascade",
"Morphology",
"PatchModelAddDownscale", "PatchModelAddDownscale",
"PerpNeg", "PerpNeg",
"PerpNegGuider",
"PerturbedAttentionGuidance",
"PhotoMakerEncode", "PhotoMakerEncode",
"PhotoMakerLoader", "PhotoMakerLoader",
"PolyexponentialScheduler", "PolyexponentialScheduler",
"PorterDuffImageComposite", "PorterDuffImageComposite",
"PreviewImage", "PreviewImage",
"RandomNoise",
"RebatchImages", "RebatchImages",
"RebatchLatents", "RebatchLatents",
"RepeatImageBatch", "RepeatImageBatch",
@ -702,40 +489,25 @@
"RescaleCFG", "RescaleCFG",
"SDTurboScheduler", "SDTurboScheduler",
"SD_4XUpscale_Conditioning", "SD_4XUpscale_Conditioning",
"SV3D_Conditioning",
"SVD_img2vid_Conditioning", "SVD_img2vid_Conditioning",
"SamplerCustom", "SamplerCustom",
"SamplerCustomAdvanced",
"SamplerDPMAdaptative",
"SamplerDPMPP_2M_SDE", "SamplerDPMPP_2M_SDE",
"SamplerDPMPP_3M_SDE",
"SamplerDPMPP_SDE", "SamplerDPMPP_SDE",
"SamplerEulerAncestral",
"SamplerLMS",
"SaveAnimatedPNG", "SaveAnimatedPNG",
"SaveAnimatedWEBP", "SaveAnimatedWEBP",
"SaveImage", "SaveImage",
"SaveImageWebsocket",
"SaveLatent", "SaveLatent",
"SelfAttentionGuidance", "SelfAttentionGuidance",
"SetLatentNoiseMask", "SetLatentNoiseMask",
"SolidMask", "SolidMask",
"SplitImageWithAlpha", "SplitImageWithAlpha",
"SplitSigmas", "SplitSigmas",
"StableCascade_EmptyLatentImage",
"StableCascade_StageB_Conditioning",
"StableCascade_StageC_VAEEncode",
"StableCascade_SuperResolutionControlnet",
"StableZero123_Conditioning", "StableZero123_Conditioning",
"StableZero123_Conditioning_Batched", "StableZero123_Conditioning_Batched",
"StyleModelApply", "StyleModelApply",
"StyleModelLoader", "StyleModelLoader",
"ThresholdMask",
"TomePatchModel", "TomePatchModel",
"UNETLoader", "UNETLoader",
"UNetCrossAttentionMultiply",
"UNetSelfAttentionMultiply",
"UNetTemporalAttentionMultiply",
"UpscaleModelLoader", "UpscaleModelLoader",
"VAEDecode", "VAEDecode",
"VAEDecodeTiled", "VAEDecodeTiled",
@ -746,7 +518,6 @@
"VAESave", "VAESave",
"VPScheduler", "VPScheduler",
"VideoLinearCFGGuidance", "VideoLinearCFGGuidance",
"VideoTriangleCFGGuidance",
"unCLIPCheckpointLoader", "unCLIPCheckpointLoader",
"unCLIPConditioning" "unCLIPConditioning"
], ],
@ -754,62 +525,6 @@
"title_aux": "ComfyUI" "title_aux": "ComfyUI"
} }
], ],
"https://github.com/dezi-ai/ComfyUI-AnimateLCM": [
[
"ADE_AdjustPEFullStretch",
"ADE_AdjustPEManual",
"ADE_AdjustPESweetspotStretch",
"ADE_AnimateDiffCombine",
"ADE_AnimateDiffKeyframe",
"ADE_AnimateDiffLoRALoader",
"ADE_AnimateDiffLoaderGen1",
"ADE_AnimateDiffLoaderV1Advanced",
"ADE_AnimateDiffLoaderWithContext",
"ADE_AnimateDiffModelSettings",
"ADE_AnimateDiffModelSettingsAdvancedAttnStrengths",
"ADE_AnimateDiffModelSettingsSimple",
"ADE_AnimateDiffModelSettings_Release",
"ADE_AnimateDiffSamplingSettings",
"ADE_AnimateDiffSettings",
"ADE_AnimateDiffUniformContextOptions",
"ADE_AnimateDiffUnload",
"ADE_ApplyAnimateDiffModel",
"ADE_ApplyAnimateDiffModelSimple",
"ADE_BatchedContextOptions",
"ADE_EmptyLatentImageLarge",
"ADE_IterationOptsDefault",
"ADE_IterationOptsFreeInit",
"ADE_LoadAnimateDiffModel",
"ADE_LoopedUniformContextOptions",
"ADE_LoopedUniformViewOptions",
"ADE_MaskedLoadLora",
"ADE_MultivalDynamic",
"ADE_MultivalScaledMask",
"ADE_NoiseLayerAdd",
"ADE_NoiseLayerAddWeighted",
"ADE_NoiseLayerReplace",
"ADE_StandardStaticContextOptions",
"ADE_StandardStaticViewOptions",
"ADE_StandardUniformContextOptions",
"ADE_StandardUniformViewOptions",
"ADE_UseEvolvedSampling",
"ADE_ViewsOnlyContextOptions",
"AnimateDiffLoaderV1",
"CheckpointLoaderSimpleWithNoiseSelect"
],
{
"title_aux": "ComfyUI Animate LCM"
}
],
"https://github.com/dfl/comfyui-stylegan": [
[
"StyleGAN Generator",
"StyleGAN ModelLoader"
],
{
"title_aux": "comfyui-stylegan"
}
],
"https://github.com/dnl13/ComfyUI-dnl13-seg": [ "https://github.com/dnl13/ComfyUI-dnl13-seg": [
[ [
"Automatic Segmentation (dnl13)", "Automatic Segmentation (dnl13)",
@ -840,41 +555,25 @@
[ [
"ApplyVoiceFixer", "ApplyVoiceFixer",
"BatchAudio", "BatchAudio",
"BlendAudio", "ClipAudio",
"ClipAudioRegion",
"CombineImageWithAudio", "CombineImageWithAudio",
"ConcatAudio", "ConcatAudio",
"ConvertAudio", "ConvertAudio",
"FilterAudio",
"FlattenAudioBatch", "FlattenAudioBatch",
"HifiGANApply",
"HifiGANLoader",
"HifiGANModelParams",
"InvertAudioPhase",
"LoadAudio", "LoadAudio",
"MusicgenGenerate", "MusicgenGenerate",
"MusicgenHFGenerate", "MusicgenHFGenerate",
"MusicgenHFLoader", "MusicgenHFLoader",
"MusicgenLoader", "MusicgenLoader",
"NormalizeAudio",
"PreviewAudio", "PreviewAudio",
"ResampleAudio",
"SaveAudio", "SaveAudio",
"SpectrogramImage", "SpectrogramImage",
"Tacotron2Generate",
"Tacotron2Loader",
"ToMelSpectrogram",
"TortoiseTTSGenerate", "TortoiseTTSGenerate",
"TortoiseTTSLoader", "TortoiseTTSLoader",
"TrimAudio",
"TrimAudioSamples",
"TrimSilence",
"VALLEXGenerator", "VALLEXGenerator",
"VALLEXLoader", "VALLEXLoader",
"VALLEXVoicePromptFromAudio", "VALLEXVoicePromptFromAudio",
"VALLEXVoicePromptLoader", "VALLEXVoicePromptLoader"
"WaveGlowApply",
"WaveGlowLoader"
], ],
{ {
"title_aux": "ComfyUI-audio" "title_aux": "ComfyUI-audio"
@ -907,75 +606,9 @@
"title_aux": "ComfyUI_stable_fast" "title_aux": "ComfyUI_stable_fast"
} }
], ],
"https://github.com/houdinii/comfy-magick": [
[
"AdaptiveBlur",
"AdaptiveSharpen",
"AddNoise",
"BlueShift",
"Blur",
"Charcoal",
"Colorize",
"CropByAspectRatio",
"Despeckle",
"Edge",
"Emboss",
"FX",
"GaussianBlur",
"Implode",
"Kuwahara",
"MotionBlur",
"RotationalBlur",
"SelectiveBlur",
"Sepia",
"Shade",
"Sharpen",
"Sketch",
"Solarize",
"Spread",
"Stereogram",
"Swirl",
"Tint",
"UnsharpMask",
"Vignette",
"WaveletDenoise"
],
{
"title_aux": "comfy-magick [WIP]"
}
],
"https://github.com/huizhang0110/ComfyUI_Easy_Nodes_hui": [
[
"EasyBgRemover",
"EasyBgRemover_ModelLoader",
"EasyControlNetApply",
"EasyControlNetLoader",
"EasyEmptyLatentImage",
"EasyLatentToCondition",
"EasyLoadImage"
],
{
"title_aux": "ComfyUI_Easy_Nodes_hui"
}
],
"https://github.com/hy134300/comfyui-hb-node": [
[
"generate story",
"hy save image",
"latent to list",
"movie batch",
"movie generate",
"sound voice",
"text concat"
],
{
"title_aux": "comfyui-hb-node"
}
],
"https://github.com/ilovejohnwhite/UncleBillyGoncho": [ "https://github.com/ilovejohnwhite/UncleBillyGoncho": [
[ [
"CannyEdgePreprocessor", "CannyEdgePreprocessor",
"DiffusionEdge_Preprocessor",
"HintImageEnchance", "HintImageEnchance",
"ImageGenResolutionFromImage", "ImageGenResolutionFromImage",
"ImageGenResolutionFromLatent", "ImageGenResolutionFromLatent",
@ -1069,18 +702,22 @@
"title_aux": "jn_node_suite_comfyui [WIP]" "title_aux": "jn_node_suite_comfyui [WIP]"
} }
], ],
"https://github.com/kadirnar/ComfyUI-Adapter": [ "https://github.com/kadirnar/ComfyUI-Transformers": [
[ [
"GarmentSegLoader" "DepthEstimationPipeline"
], ],
{ {
"title_aux": "ComfyUI-Adapter [WIP]" "title_aux": "ComfyUI-Transformers"
} }
], ],
"https://github.com/kadirnar/comfyui_helpers": [ "https://github.com/kadirnar/comfyui_helpers": [
[ [
"CLIPSeg",
"CircularVAEDecode", "CircularVAEDecode",
"CombineMasks",
"CustomKSamplerAdvancedTile", "CustomKSamplerAdvancedTile",
"ImageLoaderAndProcessor",
"ImageToContrastMask",
"JDC_AutoContrast", "JDC_AutoContrast",
"JDC_BlendImages", "JDC_BlendImages",
"JDC_BrownNoise", "JDC_BrownNoise",
@ -1108,23 +745,13 @@
], ],
"https://github.com/kappa54m/ComfyUI_Usability": [ "https://github.com/kappa54m/ComfyUI_Usability": [
[ [
"KLoadImageByPath", "LoadImageByPath",
"KLoadImageByPathAdvanced", "LoadImageDedup"
"KLoadImageDedup"
], ],
{ {
"title_aux": "ComfyUI_Usability (WIP)" "title_aux": "ComfyUI_Usability (WIP)"
} }
], ],
"https://github.com/kijai/ComfyUI-DeepSeek-VL": [
[
"deepseek_vl_inference",
"deepseek_vl_model_loader"
],
{
"title_aux": "ComfyUI nodes to use DeepSeek-VL"
}
],
"https://github.com/komojini/ComfyUI_Prompt_Template_CustomNodes/raw/main/prompt_with_template.py": [ "https://github.com/komojini/ComfyUI_Prompt_Template_CustomNodes/raw/main/prompt_with_template.py": [
[ [
"ObjectPromptWithTemplate", "ObjectPromptWithTemplate",
@ -1142,16 +769,6 @@
"title_aux": "ssd-1b-comfyui" "title_aux": "ssd-1b-comfyui"
} }
], ],
"https://github.com/logtd/ComfyUI-MotionThiefExperiment": [
[
"ApplyRefMotionNode",
"MotionRefSettingsCustomNode",
"MotionRefSettingsDefaultNode"
],
{
"title_aux": "ComfyUI-MotionThiefExperiment"
}
],
"https://github.com/ltdrdata/ComfyUI-Workflow-Component": [ "https://github.com/ltdrdata/ComfyUI-Workflow-Component": [
[ [
"ComboToString", "ComboToString",
@ -1170,22 +787,6 @@
"title_aux": "ComfyUI-Workflow-Component [WIP]" "title_aux": "ComfyUI-Workflow-Component [WIP]"
} }
], ],
"https://github.com/marcueberall/ComfyUI-BuildPath": [
[
"Build Path Adv"
],
{
"title_aux": "ComfyUI-BuildPath"
}
],
"https://github.com/mut-ex/comfyui-gligengui-node": [
[
"GLIGEN_GUI"
],
{
"title_aux": "ComfyUI GLIGEN GUI Node"
}
],
"https://github.com/nidefawl/ComfyUI-nidefawl": [ "https://github.com/nidefawl/ComfyUI-nidefawl": [
[ [
"BlendImagesWithBoundedMasks", "BlendImagesWithBoundedMasks",
@ -1219,9 +820,7 @@
"PromptUtilitiesFormatString", "PromptUtilitiesFormatString",
"PromptUtilitiesJoinStringList", "PromptUtilitiesJoinStringList",
"PromptUtilitiesLoadPreset", "PromptUtilitiesLoadPreset",
"PromptUtilitiesLoadPresetAdvanced", "PromptUtilitiesLoadPresetAdvanced"
"PromptUtilitiesRandomPreset",
"PromptUtilitiesRandomPresetAdvanced"
], ],
{ {
"title_aux": "ComfyUI-PromptUtilities" "title_aux": "ComfyUI-PromptUtilities"
@ -1269,108 +868,6 @@
"title_aux": "prism-tools" "title_aux": "prism-tools"
} }
], ],
"https://github.com/sdfxai/SDFXBridgeForComfyUI": [
[
"SDFXClipTextEncode"
],
{
"title_aux": "SDFXBridgeForComfyUI - ComfyUI Custom Node for SDFX Integration"
}
],
"https://github.com/shadowcz007/comfyui-CLIPSeg": [
[
"CLIPSeg_",
"CombineMasks_"
],
{
"title_aux": "comfyui-CLIPSeg"
}
],
"https://github.com/shadowcz007/comfyui-musicgen": [
[
"Musicgen"
],
{
"title_aux": "comfyui-musicgen"
}
],
"https://github.com/shirazdesigner/CLIPTextEncodeAndEnhancev4": [
[
"CLIPTextEncodeAndEnhance"
],
{
"title_aux": "CLIPTextEncodeAndEnhancev4 (shirazdesigner)"
}
],
"https://github.com/stutya/ComfyUI-Terminal": [
[
"Terminal"
],
{
"title_aux": "ComfyUI-Terminal [UNSAFE]"
}
],
"https://github.com/sugarkwork/comfyui_psd": [
[
"SavePSD"
],
{
"title_aux": "comfyui_psd [WIP]"
}
],
"https://github.com/tjorbogarden/my-useful-comfyui-custom-nodes": [
[
"ImageSizer",
"KSamplerSDXLAdvanced"
],
{
"title_aux": "my-useful-comfyui-custom-nodes"
}
],
"https://github.com/tuckerdarby/ComfyUI-TDNodes": [
[
"HandTrackerNode",
"InstanceDiffusionLoader",
"InstanceTrackerPrompt",
"KSamplerBatchedNode",
"KSamplerRAVE",
"KSamplerTF",
"TemporalNetPreprocessor",
"TrackerNode",
"VideoTrackerPromptNode"
],
{
"title_aux": "ComfyUI-TDNodes [WIP]"
}
],
"https://github.com/umisetokikaze/comfyui_mergekit": [
[
"DefineSaveName",
"LoadLR",
"LoadTarget",
"Merge",
"SetLayer",
"SetModels",
"SetTokenizer",
"get_skip"
],
{
"title_aux": "comfyui_mergekit [WIP]"
}
],
"https://github.com/unanan/ComfyUI-Dist": [
[
"LoadCheckpointFromLAN",
"LoadCheckpointFromURL",
"LoadImageFromLAN",
"LoadImageFromURL",
"LoadWorkflowFromLAN",
"LoadWorkflowFromURL"
],
{
"title_aux": "ComfyUI-Dist [WIP]"
}
],
"https://github.com/unanan/ComfyUI-clip-interrogator": [ "https://github.com/unanan/ComfyUI-clip-interrogator": [
[ [
"ComfyUIClipInterrogator", "ComfyUIClipInterrogator",

350
node_db/dev/github-stats.json

@ -1,350 +0,0 @@
{
"https://github.com/longgui0318/comfyui-one-more-step": {
"stars": 0,
"last_update": "2024-04-28 10:33:08"
},
"https://github.com/TemryL/ComfyUI-IDM-VTON": {
"stars": 11,
"last_update": "2024-04-28 23:39:01"
},
"https://github.com/shirazdesigner/CLIPTextEncodeAndEnhancev4": {
"stars": 0,
"last_update": "2024-04-27 13:25:08"
},
"https://github.com/umisetokikaze/comfyui_mergekit": {
"stars": 0,
"last_update": "2024-04-28 07:21:00"
},
"https://github.com/Video3DGenResearch/comfyui-batch-input-node": {
"stars": 1,
"last_update": "2024-04-28 15:21:17"
},
"https://github.com/kijai/ComfyUI-DeepSeek-VL": {
"stars": 12,
"last_update": "2024-04-23 18:10:42"
},
"https://github.com/GentlemanHu/ComfyUI-Notifier": {
"stars": 1,
"last_update": "2024-04-26 04:22:25"
},
"https://github.com/nat-chan/comfyui-in-memory-transceiver": {
"stars": 1,
"last_update": "2024-04-24 04:11:05"
},
"https://github.com/DrMWeigand/ComfyUI_LineBreakInserter": {
"stars": 0,
"last_update": "2024-04-19 11:37:19"
},
"https://github.com/WilliamStanford/visuallabs_comfyui_nodes": {
"stars": 1,
"last_update": "2024-04-16 21:53:02"
},
"https://github.com/bruce007lee/comfyui-cleaner": {
"stars": 2,
"last_update": "2024-04-20 15:36:03"
},
"https://github.com/ExponentialML/ComfyUI_LiveDirector": {
"stars": 32,
"last_update": "2024-04-09 19:01:49"
},
"https://github.com/logtd/ComfyUI-MotionThiefExperiment": {
"stars": 34,
"last_update": "2024-04-09 01:00:51"
},
"https://github.com/hy134300/comfyui-hb-node": {
"stars": 0,
"last_update": "2024-04-09 09:56:22"
},
"https://github.com/gameltb/io_comfyui": {
"stars": 3,
"last_update": "2024-04-06 04:40:05"
},
"https://github.com/ALatentPlace/ComfyUI_yanc": {
"stars": 4,
"last_update": "2024-04-16 19:03:34"
},
"https://github.com/Jiffies-64/ComfyUI-SaveImagePlus": {
"stars": 0,
"last_update": "2024-04-01 10:52:59"
},
"https://github.com/kadirnar/ComfyUI-Adapter": {
"stars": 3,
"last_update": "2024-04-03 12:05:39"
},
"https://github.com/Beinsezii/comfyui-amd-go-fast": {
"stars": 3,
"last_update": "2024-03-31 01:17:57"
},
"https://github.com/sugarkwork/comfyui_psd": {
"stars": 0,
"last_update": "2024-03-26 08:24:56"
},
"https://github.com/SadaleNet/ComfyUI-Prompt-To-Prompt": {
"stars": 15,
"last_update": "2024-03-17 04:30:01"
},
"https://github.com/MushroomFleet/DJZ-Nodes": {
"stars": 3,
"last_update": "2024-03-18 11:18:42"
},
"https://github.com/stavsap/ComfyUI-React-SDK": {
"stars": 5,
"last_update": "2024-03-17 21:54:21"
},
"https://github.com/chaojie/ComfyUI-DynamiCrafter": {
"stars": 86,
"last_update": "2024-03-16 19:08:28"
},
"https://github.com/cubiq/Comfy_Dungeon": {
"stars": 134,
"last_update": "2024-04-26 11:00:58"
},
"https://github.com/dfl/comfyui-stylegan": {
"stars": 1,
"last_update": "2024-03-14 14:34:25"
},
"https://github.com/christian-byrne/elimination-nodes": {
"stars": 4,
"last_update": "2024-04-09 18:51:29"
},
"https://github.com/A719689614/ComfyUI_AC_FUNV8Beta1": {
"stars": 12,
"last_update": "2024-03-08 10:11:44"
},
"https://github.com/houdinii/comfy-magick": {
"stars": 4,
"last_update": "2024-03-11 06:40:54"
},
"https://github.com/tjorbogarden/my-useful-comfyui-custom-nodes": {
"stars": 0,
"last_update": "2024-03-05 13:31:31"
},
"https://github.com/DeTK/ComfyUI-Switch": {
"stars": 0,
"last_update": "2024-03-04 11:52:04"
},
"https://github.com/GrindHouse66/ComfyUI-GH_Tools": {
"stars": 0,
"last_update": "2024-03-10 13:27:14"
},
"https://github.com/sdfxai/SDFXBridgeForComfyUI": {
"stars": 2,
"last_update": "2024-04-12 14:09:45"
},
"https://github.com/SeedV/ComfyUI-SeedV-Nodes": {
"stars": 1,
"last_update": "2024-04-23 07:56:19"
},
"https://github.com/mut-ex/comfyui-gligengui-node": {
"stars": 24,
"last_update": "2024-02-28 02:46:05"
},
"https://github.com/unanan/ComfyUI-Dist": {
"stars": 4,
"last_update": "2024-02-28 10:03:50"
},
"https://github.com/NicholasKao1029/comfyui-hook": {
"stars": 0,
"last_update": "2024-03-07 05:50:56"
},
"https://github.com/Extraltodeus/Conditioning-token-experiments-for-ComfyUI": {
"stars": 13,
"last_update": "2024-03-10 01:04:02"
},
"https://github.com/shadowcz007/comfyui-llamafile": {
"stars": 10,
"last_update": "2024-04-29 08:35:31"
},
"https://github.com/gameltb/ComfyUI_paper_playground": {
"stars": 7,
"last_update": "2024-04-06 10:30:44"
},
"https://github.com/huizhang0110/ComfyUI_Easy_Nodes_hui": {
"stars": 2,
"last_update": "2024-02-27 08:22:49"
},
"https://github.com/tuckerdarby/ComfyUI-TDNodes": {
"stars": 3,
"last_update": "2024-02-19 17:00:55"
},
"https://github.com/shadowcz007/comfyui-musicgen": {
"stars": 0,
"last_update": "2024-02-13 08:45:12"
},
"https://github.com/shadowcz007/comfyui-CLIPSeg": {
"stars": 0,
"last_update": "2024-02-08 02:16:24"
},
"https://github.com/dezi-ai/ComfyUI-AnimateLCM": {
"stars": 127,
"last_update": "2024-02-07 17:34:39"
},
"https://github.com/stutya/ComfyUI-Terminal": {
"stars": 0,
"last_update": "2024-02-05 16:47:28"
},
"https://github.com/marcueberall/ComfyUI-BuildPath": {
"stars": 0,
"last_update": "2024-02-06 07:57:33"
},
"https://github.com/LotzF/ComfyUI-Simple-Chat-GPT-completion": {
"stars": 0,
"last_update": "2024-02-04 21:15:22"
},
"https://github.com/kappa54m/ComfyUI_Usability": {
"stars": 0,
"last_update": "2024-02-05 14:49:45"
},
"https://github.com/17Retoucher/ComfyUI_Fooocus": {
"stars": 50,
"last_update": "2024-02-24 07:33:29"
},
"https://github.com/nkchocoai/ComfyUI-PromptUtilities": {
"stars": 6,
"last_update": "2024-02-21 14:47:42"
},
"https://github.com/BadCafeCode/execution-inversion-demo-comfyui": {
"stars": 3,
"last_update": "2024-03-23 23:53:13"
},
"https://github.com/unanan/ComfyUI-clip-interrogator": {
"stars": 18,
"last_update": "2024-02-01 09:46:57"
},
"https://github.com/prismwastaken/comfyui-tools": {
"stars": 0,
"last_update": "2024-03-05 14:34:56"
},
"https://github.com/poisenbery/NudeNet-Detector-Provider": {
"stars": 1,
"last_update": "2024-02-26 02:11:27"
},
"https://github.com/LarryJane491/ComfyUI-ModelUnloader": {
"stars": 1,
"last_update": "2024-01-14 08:22:39"
},
"https://github.com/AIGODLIKE/ComfyUI-Studio": {
"stars": 185,
"last_update": "2024-04-03 03:59:31"
},
"https://github.com/MrAdamBlack/CheckProgress": {
"stars": 1,
"last_update": "2024-01-10 08:02:18"
},
"https://github.com/birnam/ComfyUI-GenData-Pack": {
"stars": 0,
"last_update": "2024-03-25 01:25:23"
},
"https://github.com/ZHO-ZHO-ZHO/ComfyUI-AnyText": {
"stars": 38,
"last_update": "2024-01-07 11:48:05"
},
"https://github.com/nidefawl/ComfyUI-nidefawl": {
"stars": 0,
"last_update": "2024-01-16 18:16:41"
},
"https://github.com/kadirnar/comfyui_helpers": {
"stars": 2,
"last_update": "2024-03-04 16:25:30"
},
"https://github.com/foglerek/comfyui-cem-tools": {
"stars": 1,
"last_update": "2024-01-13 23:22:07"
},
"https://github.com/talesofai/comfyui-supersave": {
"stars": 1,
"last_update": "2023-12-27 02:05:53"
},
"https://github.com/Sai-ComfyUI/ComfyUI-MS-Nodes": {
"stars": 2,
"last_update": "2024-02-22 08:34:44"
},
"https://github.com/eigenpunk/ComfyUI-audio": {
"stars": 44,
"last_update": "2024-03-03 21:14:14"
},
"https://github.com/Jaxkr/comfyui-terminal-command": {
"stars": 1,
"last_update": "2023-12-03 10:31:40"
},
"https://github.com/BlueDangerX/ComfyUI-BDXNodes": {
"stars": 1,
"last_update": "2023-12-10 04:01:19"
},
"https://github.com/ilovejohnwhite/UncleBillyGoncho": {
"stars": 0,
"last_update": "2024-02-29 00:16:42"
},
"https://github.com/IvanZhd/comfyui-codeformer": {
"stars": 0,
"last_update": "2023-12-02 20:51:52"
},
"https://github.com/alt-key-project/comfyui-dream-video-batches": {
"stars": 46,
"last_update": "2023-12-03 10:31:55"
},
"https://github.com/oyvindg/ComfyUI-TrollSuite": {
"stars": 0,
"last_update": "2023-11-21 01:46:07"
},
"https://github.com/romeobuilderotti/ComfyUI-EZ-Pipes": {
"stars": 3,
"last_update": "2023-11-15 22:00:49"
},
"https://github.com/wormley/comfyui-wormley-nodes": {
"stars": 0,
"last_update": "2023-11-12 19:05:11"
},
"https://github.com/dnl13/ComfyUI-dnl13-seg": {
"stars": 17,
"last_update": "2024-01-08 10:52:13"
},
"https://github.com/phineas-pta/comfy-trt-test": {
"stars": 77,
"last_update": "2024-03-10 21:17:56"
},
"https://github.com/Brandelan/ComfyUI_bd_customNodes": {
"stars": 1,
"last_update": "2023-10-09 00:40:26"
},
"https://github.com/Jordach/comfy-consistency-vae": {
"stars": 68,
"last_update": "2023-11-06 20:50:40"
},
"https://github.com/gameltb/ComfyUI_stable_fast": {
"stars": 174,
"last_update": "2024-04-01 13:30:57"
},
"https://github.com/jn-jairo/jn_node_suite_comfyui": {
"stars": 5,
"last_update": "2024-01-11 20:39:36"
},
"https://github.com/PluMaZero/ComfyUI-SpaceFlower": {
"stars": 4,
"last_update": "2023-12-09 05:55:15"
},
"https://github.com/laksjdjf/ssd-1b-comfyui": {
"stars": 1,
"last_update": "2023-10-27 20:05:06"
},
"https://github.com/flowtyone/comfyui-flowty-lcm": {
"stars": 62,
"last_update": "2023-10-23 12:08:55"
},
"https://github.com/doucx/ComfyUI_WcpD_Utility_Kit": {
"stars": 1,
"last_update": "2024-01-06 19:07:45"
},
"https://github.com/WSJUSA/Comfyui-StableSR": {
"stars": 32,
"last_update": "2023-10-18 12:40:30"
},
"https://github.com/ltdrdata/ComfyUI-Workflow-Component": {
"stars": 181,
"last_update": "2024-04-26 01:39:09"
},
"https://github.com/comfyanonymous/ComfyUI": {
"stars": 33530,
"last_update": "2024-04-29 00:08:28"
}
}

40
node_db/forked/custom-node-list.json

@ -1,45 +1,5 @@
{ {
"custom_nodes": [ "custom_nodes": [
{
"author": "meimeilook",
"title": "ComfyUI_IPAdapter_plus.old [backward compatbility]",
"reference": "https://github.com/meimeilook/ComfyUI_IPAdapter_plus.old",
"files": [
"https://github.com/meimeilook/ComfyUI_IPAdapter_plus.old"
],
"install_type": "git-clone",
"description": "This repo is created to provide backward compatibility for workflows configured with the old IPAdapter."
},
{
"author": "ZHO-ZHO-ZHO",
"title": "Dr.Lt.Data/ComfyUI-YoloWorld-EfficientSAM",
"reference": "https://github.com/ltdrdata/ComfyUI-YoloWorld-EfficientSAM",
"files": [
"https://github.com/ltdrdata/ComfyUI-YoloWorld-EfficientSAM"
],
"install_type": "git-clone",
"description": "This fork includes [a/PR32](https://github.com/ZHO-ZHO-ZHO/ComfyUI-YoloWorld-EfficientSAM/pull/32)"
},
{
"author": "ertu110",
"title": "sdxl_prompt_style",
"reference": "https://github.com/ertu110/sdxl_prompt_style",
"files": [
"https://github.com/ertu110/sdxl_prompt_style"
],
"install_type": "git-clone",
"description": "This project is a complete benchmark [a/https://github.com/twri/sdxl_prompt_styler](https://github.com/twri/sdxl_prompt_styler) A large amount of code inside comes from https://github.com/twri/sdxl_prompt_styler Project and [a/https://www.nodecafe.org/package/pythongosssss_ComfyUI-Custom-Scripts](https://www.nodecafe.org/package/pythongosssss_ComfyUI-Custom-Scripts) project\nThe functionality of this project is related to https://github.com/twri/sdxl_prompt_styler Highly overlapping, the only purpose of creating this project is because there are too many styles when selecting, resulting in a long and inconvenient dropdown box. Therefore, To address this issue, this project has added a secondary menu to the style."
},
{
"author": "gustproof",
"title": "ComfyUI_IPAdapter_plus_Style_Components",
"reference": "https://github.com/gustproof/ComfyUI_IPAdapter_plus_Style_Components",
"files": [
"https://github.com/gustproof/ComfyUI_IPAdapter_plus_Style_Components"
],
"install_type": "git-clone",
"description": "Style Components is an IP-Adapter model conditioned on anime styles. The style embeddings can either be extracted from images or created manually. This repo currently only supports the SDXL model trained on AutismmixPony."
},
{ {
"author": "gameltb", "author": "gameltb",
"title": "comfyui-stablsr", "title": "comfyui-stablsr",

172
node_db/legacy/custom-node-list.json

@ -8,178 +8,8 @@
"install_type": "git-clone", "install_type": "git-clone",
"description": "If you see this message, your ComfyUI-Manager is outdated.\nLegacy channel provides only the list of the deprecated nodes. If you want to find the complete node list, please go to the Default channel." "description": "If you see this message, your ComfyUI-Manager is outdated.\nLegacy channel provides only the list of the deprecated nodes. If you want to find the complete node list, please go to the Default channel."
}, },
{
"author": "IKHOR",
"title": "ikhor-nodes [REMOVED]",
"reference": "https://github.com/IKHOR/ComfyUI-IKHOR-Jam-Nodes",
"files": [
"https://github.com/IKHOR/ComfyUI-IKHOR-Jam-Nodes"
],
"install_type": "git-clone",
"description": "Nodes:LoadFromS3, LoadBatchFromS3, SaveToS3, SaveBatchToS3"
},
{
"author": "kijai",
"title": "ComfyUI wrapper nodes for IC-light [DEPRECATED]",
"reference": "https://github.com/kijai/ComfyUI-IC-Light-Wrapper",
"files": [
"https://github.com/kijai/ComfyUI-IC-Light-Wrapper"
],
"install_type": "git-clone",
"description": "Stopped. Original repo: [a/https://github.com/lllyasviel/IC-Light](https://github.com/lllyasviel/IC-Light)"
},
{
"author": "thedyze",
"title": "Save Image Extended for ComfyUI",
"reference": "https://github.com/thedyze/save-image-extended-comfyui",
"files": [
"https://github.com/thedyze/save-image-extended-comfyui"
],
"install_type": "git-clone",
"description": "Customize the information saved in file- and folder names. Use the values of sampler parameters as part of file or folder names. Save your positive & negative prompt as entries in a JSON (text) file, in each folder.\n[w/This custom node has not been maintained for a long time. Please use an alternative node from the default channel.]"
},
{
"author": "ExponentialML",
"title": "ComfyUI_ELLA [DEPRECATED]",
"reference": "https://github.com/ExponentialML/ComfyUI_ELLA",
"files": [
"https://github.com/ExponentialML/ComfyUI_ELLA"
],
"install_type": "git-clone",
"description": "ComfyUI Implementaion of ELLA: Equip Diffusion Models with LLM for Enhanced Semantic Alignment.[w/Officially implemented here: [a/https://github.com/TencentQQGYLab/ComfyUI-ELLA](https://github.com/TencentQQGYLab/ComfyUI-ELLA)]"
},
{
"author": "shinich39",
"title": "comfyui-text-pipe-39 [DEPRECATED]",
"reference": "https://github.com/shinich39/comfyui-text-pipe-39",
"files": [
"https://github.com/shinich39/comfyui-text-pipe-39"
],
"install_type": "git-clone",
"description": "Modify text by condition."
},
{
"author": "Big Idea Technology",
"title": "Image Text Overlay Node for ComfyUI [DEPRECATED]",
"reference": "https://github.com/Big-Idea-Technology/ComfyUI_Image_Text_Overlay",
"files": [
"https://github.com/Big-Idea-Technology/ComfyUI_Image_Text_Overlay"
],
"install_type": "git-clone",
"description": "Please note that the ImageTextOverlay project is no longer supported and has been moved to a new repository. For ongoing developments, contributions, and issues, please refer to the new repository at: [a/https://github.com/Big-Idea-Technology/ComfyUI-Book-Tools](https://github.com/Big-Idea-Technology/ComfyUI-Book-Tools)"
},
{
"author": "mlinmg",
"title": "LaMa Preprocessor [DEPRECATED]",
"reference": "https://github.com/mlinmg/ComfyUI-LaMA-Preprocessor",
"files": [
"https://github.com/mlinmg/ComfyUI-LaMA-Preprocessor"
],
"install_type": "git-clone",
"description": "A LaMa prerocessor for ComfyUI. This preprocessor finally enable users to generate coherent inpaint and outpaint prompt-free. The best results are given on landscapes, not so much in drawings/animation."
},
{
"author": "CapsAdmin",
"title": "ComfyUI-Euler-Smea-Dyn-Sampler [DEPRECATED]",
"reference": "https://github.com/CapsAdmin/ComfyUI-Euler-Smea-Dyn-Sampler",
"files": [
"https://github.com/CapsAdmin/ComfyUI-Euler-Smea-Dyn-Sampler"
],
"install_type": "git-clone",
"description": "Just a comfyui version of [a/Euler Smea Dyn Sampler](https://github.com/Koishi-Star/Euler-Smea-Dyn-Sampler). It adds the sampler directly to existing samplers."
},
{
"author": "BlakeOne",
"title": "ComfyUI FastImageListToImageBatch [REMOVED]",
"reference": "https://github.com/BlakeOne/ComfyUI-FastImageListToImageBatch",
"files": [
"https://github.com/BlakeOne/ComfyUI-FastImageListToImageBatch"
],
"install_type": "git-clone",
"description": "Quickly convert a list of images to a batch of images. All images must be the same size. Great for long videos."
},
{
"author": "ggpid",
"title": "idpark_custom_node [REMOVED]",
"reference": "https://github.com/ggpid/idpark_custom_node",
"files": [
"https://github.com/ggpid/idpark_custom_node"
],
"install_type": "git-clone",
"description": "Nodes:Load Image from S3, Save Image to S3, Generate SAM, Generate FastSAM, Cut by Mask fixed"
},
{
"author": "Davemane42",
"title": "Visual Area Conditioning / Latent composition [DEPRECATED]",
"reference": "https://github.com/Davemane42/ComfyUI_Dave_CustomNode",
"files": [
"https://github.com/Davemane42/ComfyUI_Dave_CustomNode"
],
"install_type": "git-clone",
"description": "This tool provides custom nodes that allow visualization and configuration of area conditioning and latent composite."
},
{
"author": "laksjdjf",
"title": "LoRA-Merger-ComfyUI [DEPRECATED]",
"reference": "https://github.com/laksjdjf/LoRA-Merger-ComfyUI",
"files": [
"https://github.com/laksjdjf/LoRA-Merger-ComfyUI"
],
"install_type": "git-clone",
"description": "Nodes:Load LoRA Weight Only, Load LoRA from Weight, Merge LoRA, Save LoRA. This extension provides nodes for merging LoRA."
},
{
"author": "kinfolk0117",
"title": "TiledIPAdapter [DEPRECATED]",
"reference": "https://github.com/kinfolk0117/ComfyUI_TiledIPAdapter",
"files": [
"https://github.com/kinfolk0117/ComfyUI_TiledIPAdapter"
],
"install_type": "git-clone",
"description": "Proof of concent on how to use IPAdapter to control tiled upscaling. NOTE: You need to have 'ComfyUI_IPAdapter_plus' installed."
},
{
"author": "XINZHANG-ops",
"title": "comfyui-xin-nodes [REMOVED]",
"reference": "https://github.com/XINZHANG-ops/comfyui-xin-nodes",
"files": [
"https://github.com/XINZHANG-ops/comfyui-xin-nodes"
],
"install_type": "git-clone",
"description": "Nodes:ImageSizeClassifer, RandomInt, ShowValue"
},
{
"author": "ssitu",
"title": "NestedNodeBuilder [DEPRECATED]",
"reference": "https://github.com/ssitu/ComfyUI_NestedNodeBuilder",
"files": [
"https://github.com/ssitu/ComfyUI_NestedNodeBuilder"
],
"install_type": "git-clone",
"description": "This extension provides the ability to combine multiple nodes into a single node.\nNOTE:An identical feature now exists in ComfyUI. Additionally, this extension is largely broken with the recent versions of the codebase, so please use the built-in feature for group nodes."
},
{
"author": "ccvv804",
"title": "ComfyUI StableCascade using diffusers for Low VRAM [DEPRECATED]",
"reference": "https://github.com/ccvv804/ComfyUI-DiffusersStableCascade-LowVRAM",
"files": [
"https://github.com/ccvv804/ComfyUI-DiffusersStableCascade-LowVRAM"
],
"install_type": "git-clone",
"description": "Works with RTX 4070ti 12GB.\nSimple quick wrapper for [a/https://huggingface.co/stabilityai/stable-cascade](https://huggingface.co/stabilityai/stable-cascade)\nComfy is going to implement this properly soon, this repo is just for quick testing for the impatient!"
},
{
"author": "kijai",
"title": "ComfyUI StableCascade using diffusers [DEPRECATED]",
"reference": "https://github.com/kijai/ComfyUI-DiffusersStableCascade",
"files": [
"https://github.com/kijai/ComfyUI-DiffusersStableCascade"
],
"install_type": "git-clone",
"description": "Simple quick wrapper for [a/https://huggingface.co/stabilityai/stable-cascade](https://huggingface.co/stabilityai/stable-cascade)\nComfy is going to implement this properly soon, this repo is just for quick testing for the impatient!"
},
{ {
"author": "solarpush", "author": "solarpush",
"title": "comfyui_sendimage_node [REMOVED]", "title": "comfyui_sendimage_node [REMOVED]",

729
node_db/new/custom-node-list.json

File diff suppressed because it is too large Load Diff

5523
node_db/new/extension-node-map.json

File diff suppressed because it is too large Load Diff

968
node_db/new/model-list.json

@ -1,493 +1,5 @@
{ {
"models": [ "models": [
{
"name": "ID-Animator/animator.ckpt",
"type": "ID-Animator",
"base": "SD1.5",
"save_path": "custom_nodes/ComfyUI_ID_Animator/models",
"description": "ID-Animator checkpoint",
"reference": "https://huggingface.co/spaces/ID-Animator/ID-Animator",
"filename": "animator.ckpt",
"url": "https://huggingface.co/spaces/ID-Animator/ID-Animator/resolve/main/animator.ckpt"
},
{
"name": "ID-Animator/mm_sd_v15_v2.ckpt",
"type": "ID-Animator",
"base": "SD1.5",
"save_path": "custom_nodes/ComfyUI_ID_Animator/models/animatediff_models",
"description": "AnimateDiff checkpoint for ID-Animator",
"reference": "https://huggingface.co/spaces/ID-Animator/ID-Animator",
"filename": "mm_sd_v15_v2.ckpt",
"url": "https://huggingface.co/spaces/ID-Animator/ID-Animator/resolve/main/mm_sd_v15_v2.ckpt"
},
{
"name": "ID-Animator/image_encoder",
"type": "ID-Animator",
"base": "SD1.5",
"save_path": "custom_nodes/ComfyUI_ID_Animator/models/image_encoder",
"description": "CLIP Image encoder for ID-Animator",
"reference": "https://huggingface.co/spaces/ID-Animator/ID-Animator",
"filename": "model.safetensors",
"url": "https://huggingface.co/spaces/ID-Animator/ID-Animator/resolve/main/image_encoder/model.safetensors"
},
{
"name": "IC-Light/fc",
"type": "IC-Light",
"base": "SD1.5",
"save_path": "unet/IC-Light",
"description": "The default relighting model, conditioned on text and foreground",
"reference": "https://huggingface.co/lllyasviel/ic-light",
"filename": "iclight_sd15_fc.safetensors",
"url": "https://huggingface.co/lllyasviel/ic-light/resolve/main/iclight_sd15_fc.safetensors"
},
{
"name": "IC-Light/fbc",
"type": "IC-Light",
"base": "SD1.5",
"save_path": "unet/IC-Light",
"description": "Relighting model conditioned with text, foreground, and background",
"reference": "https://huggingface.co/lllyasviel/ic-light",
"filename": "iclight_sd15_fbc.safetensors",
"url": "https://huggingface.co/lllyasviel/ic-light/resolve/main/iclight_sd15_fbc.safetensors"
},
{
"name": "IC-Light/fcon",
"type": "IC-Light",
"base": "SD1.5",
"save_path": "unet/IC-Light",
"description": "Same as iclight_sd15_fc.safetensors, but trained with offset noise",
"reference": "https://huggingface.co/lllyasviel/ic-light",
"filename": "iclight_sd15_fcon.safetensors",
"url": "https://huggingface.co/lllyasviel/ic-light/resolve/main/iclight_sd15_fcon.safetensors"
},
{
"name": "MonsterMMORPG/insightface (for InstantID)",
"type": "insightface",
"base": "SDXL",
"save_path": "insightface/models",
"description": "MonsterMMORPG insightface model for cubiq/InstantID",
"reference": "https://huggingface.co/MonsterMMORPG/tools/tree/main",
"filename": "antelopev2.zip",
"url": "https://huggingface.co/MonsterMMORPG/tools/resolve/main/antelopev2.zip"
},
{
"name": "InstantID/ip-adapter",
"type": "instantid",
"base": "SDXL",
"save_path": "instantid/SDXL",
"description": "ip-adapter model for cubiq/InstantID",
"reference": "https://huggingface.co/InstantX/InstantID",
"filename": "ip-adapter.bin",
"url": "https://huggingface.co/InstantX/InstantID/resolve/main/ip-adapter.bin"
},
{
"name": "InstantID/ControlNet",
"type": "controlnet",
"base": "SDXL",
"save_path": "controlnet/SDXL/instantid",
"description": "instantid controlnet model for cubiq/InstantID",
"reference": "https://huggingface.co/InstantX/InstantID",
"filename": "diffusion_pytorch_model.safetensors",
"url": "https://huggingface.co/InstantX/InstantID/resolve/main/ControlNetModel/diffusion_pytorch_model.safetensors"
},
{
"name": "ip_plus_composition_sd15.safetensors",
"type": "IP-Adapter",
"base": "SD1.5",
"save_path": "ipadapter",
"description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.",
"reference": "https://huggingface.co/ostris/ip-composition-adapter",
"filename": "ip_plus_composition_sd15.safetensors",
"url": "https://huggingface.co/ostris/ip-composition-adapter/resolve/main/ip_plus_composition_sd15.safetensors"
},
{
"name": "ip_plus_composition_sdxl.safetensors",
"type": "IP-Adapter",
"base": "SDXL",
"save_path": "ipadapter",
"description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.",
"reference": "https://huggingface.co/ostris/ip-composition-adapter",
"filename": "ip_plus_composition_sdxl.safetensors",
"url": "https://huggingface.co/ostris/ip-composition-adapter/resolve/main/ip_plus_composition_sdxl.safetensors"
},
{
"name": "ip-adapter-faceid-portrait-v11_sd15.bin",
"type": "IP-Adapter",
"base": "SD1.5",
"save_path": "ipadapter",
"description": "IP-Adapter-FaceID Portrait V11 Model (SD1.5) [ipadapter]",
"reference": "https://huggingface.co/h94/IP-Adapter-FaceID",
"filename": "ip-adapter-faceid-portrait-v11_sd15.bin",
"url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-portrait-v11_sd15.bin"
},
{
"name": "ip-adapter-faceid-portrait_sdxl.bin",
"type": "IP-Adapter",
"base": "SDXL",
"save_path": "ipadapter",
"description": "IP-Adapter-FaceID Portrait Model (SDXL) [ipadapter]",
"reference": "https://huggingface.co/h94/IP-Adapter-FaceID",
"filename": "ip-adapter-faceid-portrait_sdxl.bin",
"url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-portrait_sdxl.bin"
},
{
"name": "ip-adapter-faceid-portrait_sdxl_unnorm.bin",
"type": "IP-Adapter",
"base": "SDXL",
"save_path": "ipadapter",
"description": "IP-Adapter-FaceID Portrait Model (SDXL/unnorm) [ipadapter]",
"reference": "https://huggingface.co/h94/IP-Adapter-FaceID",
"filename": "ip-adapter-faceid-portrait_sdxl_unnorm.bin",
"url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid-portrait_sdxl_unnorm.bin"
},
{
"name": "ip-adapter_sd15_light_v11.bin",
"type": "IP-Adapter",
"base": "SD1.5",
"save_path": "ipadapter",
"description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.",
"reference": "https://huggingface.co/h94/IP-Adapter",
"filename": "ip-adapter_sd15_light_v11.bin",
"url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter_sd15_light_v11.bin"
},
{
"name": "Kijai/SUPIR-v0F_fp16.safetensors (pruned)",
"type": "checkpoints",
"base": "SUPIR",
"save_path": "checkpoints/SUPIR",
"description": "SUPIR checkpoint model",
"reference": "https://huggingface.co/Kijai/SUPIR_pruned/tree/main",
"filename": "SUPIR-v0F_fp16.safetensors",
"url": "https://huggingface.co/Kijai/SUPIR_pruned/resolve/main/SUPIR-v0F_fp16.safetensors"
},
{
"name": "Kijai/SUPIR-v0Q_fp16.safetensors (pruned)",
"type": "checkpoints",
"base": "SUPIR",
"save_path": "checkpoints/SUPIR",
"description": "SUPIR checkpoint model",
"reference": "https://huggingface.co/Kijai/SUPIR_pruned/tree/main",
"filename": "SUPIR-v0Q_fp16.safetensors",
"url": "https://huggingface.co/Kijai/SUPIR_pruned/resolve/main/SUPIR-v0Q_fp16.safetensors"
},
{
"name": "SUPIR-v0F.ckpt",
"type": "checkpoints",
"base": "SUPIR",
"save_path": "checkpoints/SUPIR",
"description": "SUPIR checkpoint model",
"reference": "https://huggingface.co/camenduru/SUPIR/tree/main",
"filename": "SUPIR-v0F.ckpt",
"url": "https://huggingface.co/camenduru/SUPIR/resolve/main/SUPIR-v0F.ckpt"
},
{
"name": "SUPIR-v0Q.ckpt",
"type": "checkpoints",
"base": "SUPIR",
"save_path": "checkpoints/SUPIR",
"description": "SUPIR checkpoint model",
"reference": "https://huggingface.co/camenduru/SUPIR/tree/main",
"filename": "SUPIR-v0Q.ckpt",
"url": "https://huggingface.co/camenduru/SUPIR/resolve/main/SUPIR-v0Q.ckpt"
},{
"name": "Depth-FM-v1 fp16 safetensors",
"type": "checkpoints",
"base": "Depth-FM",
"save_path": "checkpoints/depthfm",
"description": "Depth-FM monocular depth estimation model",
"reference": "https://huggingface.co/Kijai/depth-fm-pruned",
"filename": "depthfm-v1_fp16.safetensors",
"url": "https://huggingface.co/Kijai/depth-fm-pruned/resolve/main/depthfm-v1_fp16.safetensors"
},
{
"name": "Depth-FM-v1 fp32 safetensors",
"type": "checkpoints",
"base": "Depth-FM",
"save_path": "checkpoints/depthfm",
"description": "Depth-FM monocular depth estimation model",
"reference": "https://huggingface.co/Kijai/depth-fm-pruned",
"filename": "depthfm-v1_fp32.safetensors",
"url": "https://huggingface.co/Kijai/depth-fm-pruned/resolve/main/depthfm-v1_fp32.safetensors"
},
{
"name": "monster-labs - Controlnet QR Code Monster v1 For SDXL",
"type": "controlnet",
"base": "SDXL",
"save_path": "default",
"description": "monster-labs - Controlnet QR Code Monster v1 For SDXL",
"reference": "https://huggingface.co/monster-labs/control_v1p_sdxl_qrcode_monster",
"filename": "control_v1p_sdxl_qrcode_monster.safetensors",
"url": "https://huggingface.co/monster-labs/control_v1p_sdxl_qrcode_monster/resolve/main/diffusion_pytorch_model.safetensors"
},
{
"name": "DynamiCrafter 1024 bf16 safetensors",
"type": "checkpoints",
"base": "DynamiCrafter",
"save_path": "checkpoints/dynamicrafter",
"description": "DynamiCrafter image2video model 1024x575",
"reference": "https://huggingface.co/Kijai/DynamiCrafter_pruned/",
"filename": "dynamicrafter_1024_v1_bf16.safetensors",
"url": "https://huggingface.co/Kijai/DynamiCrafter_pruned/resolve/main/dynamicrafter_1024_v1_bf16.safetensors"
},
{
"name": "DynamiCrafter 512 interpolation bf16 safetensors",
"type": "checkpoints",
"base": "DynamiCrafter",
"save_path": "checkpoints/dynamicrafter",
"description": "DynamiCrafter image2video interpolation model 512",
"reference": "https://huggingface.co/Kijai/DynamiCrafter_pruned/",
"filename": "dynamicrafter_512_interp_v1_bf16.safetensors",
"url": "https://huggingface.co/Kijai/DynamiCrafter_pruned/resolve/main/dynamicrafter_512_interp_v1_bf16.safetensors"
},
{
"name": "MobileSAM",
"type": "sam",
"base": "SAM",
"save_path": "sams",
"description": "MobileSAM",
"reference": "https://github.com/ChaoningZhang/MobileSAM/",
"filename": "mobile_sam.pt",
"url": "https://github.com/ChaoningZhang/MobileSAM/blob/master/weights/mobile_sam.pt"
},
{
"name": "BLIP ImageCaption (COCO) w/ ViT-B and CapFilt-L",
"type": "BLIP_MODEL",
"base": "blip_model",
"save_path": "blip",
"description": "BLIP ImageCaption (COCO) w/ ViT-B and CapFilt-L",
"reference": "https://github.com/salesforce/BLIP",
"filename": "model_base_capfilt_large.pth",
"url": "https://storage.googleapis.com/sfr-vision-language-research/BLIP/models/model_base_capfilt_large.pth"
},
{
"name": "GroundingDINO SwinT OGC - Model",
"type": "GroundingDINO",
"base": "DINO",
"save_path": "groundingdino",
"description": "GroundingDINO SwinT OGC Model",
"reference": "https://huggingface.co/ShilongLiu/GroundingDINO",
"filename": "groundingdino_swint_ogc.pth",
"url": "https://huggingface.co/ShilongLiu/GroundingDINO/resolve/main/groundingdino_swint_ogc.pth"
},
{
"name": "GroundingDINO SwinT OGC - CFG File",
"type": "GroundingDINO",
"base": "DINO",
"save_path": "groundingdino",
"description": "GroundingDINO SwinT OGC CFG File",
"reference": "https://huggingface.co/ShilongLiu/GroundingDINO/resolve/main/GroundingDINO_SwinT_OGC.cfg.py",
"filename": "GroundingDINO_SwinT_OGC.cfg.py",
"url": "https://huggingface.co/ShilongLiu/GroundingDINO/raw/main/GroundingDINO_SwinT_OGC.cfg.py"
},
{
"name": "SDXL Lightning LoRA (2step)",
"type": "lora",
"base": "SDXL",
"save_path": "loras/SDXL-Lightning",
"description": "SDXL Lightning LoRA (2step)",
"reference": "https://huggingface.co/ByteDance/SDXL-Lightning",
"filename": "sdxl_lightning_2step_lora.safetensors",
"url": "https://huggingface.co/ByteDance/SDXL-Lightning/resolve/main/sdxl_lightning_2step_lora.safetensors"
},
{
"name": "SDXL Lightning LoRA (4step)",
"type": "lora",
"base": "SDXL",
"save_path": "loras/SDXL-Lightning",
"description": "SDXL Lightning LoRA (4step)",
"reference": "https://huggingface.co/ByteDance/SDXL-Lightning",
"filename": "sdxl_lightning_4step_lora.safetensors",
"url": "https://huggingface.co/ByteDance/SDXL-Lightning/resolve/main/sdxl_lightning_4step_lora.safetensors"
},
{
"name": "SDXL Lightning LoRA (8step)",
"type": "lora",
"base": "SDXL",
"save_path": "loras/SDXL-Lightning",
"description": "SDXL Lightning LoRA (8tep)",
"reference": "https://huggingface.co/ByteDance/SDXL-Lightning",
"filename": "sdxl_lightning_8step_lora.safetensors",
"url": "https://huggingface.co/ByteDance/SDXL-Lightning/resolve/main/sdxl_lightning_8step_lora.safetensors"
},
{
"name": "shape_predictor_68_face_landmarks.dat [Face Analysis]",
"type": "Shape Predictor",
"base": "DLIB",
"save_path": "custom_nodes/ComfyUI_FaceAnalysis/dlib",
"description": "To use the Face Analysis for ComfyUI custom node, installation of this model is needed.",
"reference": "https://huggingface.co/matt3ounstable/dlib_predictor_recognition/tree/main",
"filename": "shape_predictor_68_face_landmarks.dat",
"url": "https://huggingface.co/matt3ounstable/dlib_predictor_recognition/resolve/main/shape_predictor_68_face_landmarks.dat"
},
{
"name": "dlib_face_recognition_resnet_model_v1.dat [Face Analysis]",
"type": "Face Recognition",
"base": "DLIB",
"save_path": "custom_nodes/ComfyUI_FaceAnalysis/dlib",
"description": "To use the Face Analysis for ComfyUI custom node, installation of this model is needed.",
"reference": "https://huggingface.co/matt3ounstable/dlib_predictor_recognition/tree/main",
"filename": "dlib_face_recognition_resnet_model_v1.dat",
"url": "https://huggingface.co/matt3ounstable/dlib_predictor_recognition/resolve/main/dlib_face_recognition_resnet_model_v1.dat"
},
{
"name": "efficient_sam_s_cpu.jit [ComfyUI-YoloWorld-EfficientSAM]",
"type": "efficient_sam",
"base": "efficient_sam",
"save_path": "custom_nodes/ComfyUI-YoloWorld-EfficientSAM",
"description": "Install efficient_sam_s_cpu.jit into ComfyUI-YoloWorld-EfficientSAM",
"reference": "https://huggingface.co/camenduru/YoloWorld-EfficientSAM/tree/main",
"filename": "efficient_sam_s_cpu.jit",
"url": "https://huggingface.co/camenduru/YoloWorld-EfficientSAM/resolve/main/efficient_sam_s_cpu.jit"
},
{
"name": "efficient_sam_s_gpu.jit [ComfyUI-YoloWorld-EfficientSAM]",
"type": "efficient_sam",
"base": "efficient_sam",
"save_path": "custom_nodes/ComfyUI-YoloWorld-EfficientSAM",
"description": "Install efficient_sam_s_gpu.jit into ComfyUI-YoloWorld-EfficientSAM",
"reference": "https://huggingface.co/camenduru/YoloWorld-EfficientSAM/tree/main",
"filename": "efficient_sam_s_gpu.jit",
"url": "https://huggingface.co/camenduru/YoloWorld-EfficientSAM/resolve/main/efficient_sam_s_gpu.jit"
},
{
"name": "stabilityai/comfyui_checkpoints/stable_cascade_stage_b.safetensors",
"type": "checkpoints",
"base": "Stable Cascade",
"save_path": "checkpoints/Stable-Cascade",
"description": "[4.55GB] Stable Cascade stage_b checkpoints",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stable_cascade_stage_b.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/comfyui_checkpoints/stable_cascade_stage_b.safetensors"
},
{
"name": "stabilityai/comfyui_checkpoints/stable_cascade_stage_c.safetensors",
"type": "checkpoints",
"base": "Stable Cascade",
"save_path": "checkpoints/Stable-Cascade",
"description": "[9.22GB] Stable Cascade stage_c checkpoints",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stable_cascade_stage_c.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/comfyui_checkpoints/stable_cascade_stage_c.safetensors"
},
{
"name": "stabilityai/Stable Cascade: effnet_encoder.safetensors (VAE)",
"type": "VAE",
"base": "Stable Cascade",
"save_path": "vae/Stable-Cascade",
"description": "[81.5MB] Stable Cascade: effnet_encoder.\nVAE encoder for stage_c latent.",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "effnet_encoder.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/effnet_encoder.safetensors"
},
{
"name": "stabilityai/Stable Cascade: stage_a.safetensors (VAE)",
"type": "VAE",
"base": "Stable Cascade",
"save_path": "vae/Stable-Cascade",
"description": "[73.7MB] Stable Cascade: stage_a",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stage_a.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/stage_a.safetensors"
},
{
"name": "stabilityai/Stable Cascade: stage_b.safetensors (UNET)",
"type": "unet",
"base": "Stable Cascade",
"save_path": "unet/Stable-Cascade",
"description": "[6.25GB] Stable Cascade: stage_b",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stage_b.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/stage_b.safetensors"
},
{
"name": "stabilityai/Stable Cascade: stage_b_bf16.safetensors (UNET)",
"type": "unet",
"base": "Stable Cascade",
"save_path": "unet/Stable-Cascade",
"description": "[3.13GB] Stable Cascade: stage_b/bf16",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stage_b_bf16.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/stage_b_bf16.safetensors"
},
{
"name": "stabilityai/Stable Cascade: stage_b_lite.safetensors (UNET)",
"type": "unet",
"base": "Stable Cascade",
"save_path": "unet/Stable-Cascade",
"description": "[2.8GB] Stable Cascade: stage_b/lite",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stage_b_lite.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/stage_b_lite.safetensors"
},
{
"name": "stabilityai/Stable Cascade: stage_b_lite.safetensors (UNET)",
"type": "unet",
"base": "Stable Cascade",
"save_path": "unet/Stable-Cascade",
"description": "[1.4GB] Stable Cascade: stage_b/bf16,lite",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stage_b_lite_bf16.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/stage_b_lite_bf16.safetensors"
},
{
"name": "stabilityai/Stable Cascade: stage_c.safetensors (UNET)",
"type": "unet",
"base": "Stable Cascade",
"save_path": "unet/Stable-Cascade",
"description": "[14.4GB] Stable Cascade: stage_c",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stage_c.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/stage_c.safetensors"
},
{
"name": "stabilityai/Stable Cascade: stage_c_bf16.safetensors (UNET)",
"type": "unet",
"base": "Stable Cascade",
"save_path": "unet/Stable-Cascade",
"description": "[7.18GB] Stable Cascade: stage_c/bf16",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stage_c_bf16.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/stage_c_bf16.safetensors"
},
{
"name": "stabilityai/Stable Cascade: stage_c_lite.safetensors (UNET)",
"type": "unet",
"base": "Stable Cascade",
"save_path": "unet/Stable-Cascade",
"description": "[4.12GB] Stable Cascade: stage_c/lite",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stage_c_lite.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/stage_c_lite.safetensors"
},
{
"name": "stabilityai/Stable Cascade: stage_c_lite.safetensors (UNET)",
"type": "unet",
"base": "Stable Cascade",
"save_path": "unet/Stable-Cascade",
"description": "[2.06GB] Stable Cascade: stage_c/bf16,lite",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "stage_c_lite_bf16.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/stage_c_lite_bf16.safetensors"
},
{
"name": "stabilityai/Stable Cascade: text_encoder (CLIP)",
"type": "clip",
"base": "Stable Cascade",
"save_path": "clip/Stable-Cascade",
"description": "[1.39GB] Stable Cascade: text_encoder",
"reference": "https://huggingface.co/stabilityai/stable-cascade",
"filename": "model.safetensors",
"url": "https://huggingface.co/stabilityai/stable-cascade/resolve/main/text_encoder/model.safetensors"
},
{ {
"name": "1k3d68.onnx", "name": "1k3d68.onnx",
"type": "insightface", "type": "insightface",
@ -711,6 +223,486 @@
"reference": "https://huggingface.co/h94/IP-Adapter-FaceID", "reference": "https://huggingface.co/h94/IP-Adapter-FaceID",
"filename": "ip-adapter-faceid_sd15_lora.safetensors", "filename": "ip-adapter-faceid_sd15_lora.safetensors",
"url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid_sd15_lora.safetensors" "url": "https://huggingface.co/h94/IP-Adapter-FaceID/resolve/main/ip-adapter-faceid_sd15_lora.safetensors"
},
{
"name": "LongAnimatediff/lt_long_mm_16_64_frames_v1.1.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)",
"type": "animatediff",
"base": "SD1.x",
"save_path": "animatediff_models",
"description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.",
"reference": "https://huggingface.co/Lightricks/LongAnimateDiff",
"filename": "lt_long_mm_16_64_frames_v1.1.ckpt",
"url": "https://huggingface.co/Lightricks/LongAnimateDiff/resolve/main/lt_long_mm_16_64_frames_v1.1.ckpt"
},
{
"name": "animatediff/v3_sd15_sparsectrl_rgb.ckpt (ComfyUI-AnimateDiff-Evolved)",
"type": "controlnet",
"base": "SD1.x",
"save_path": "controlnet/SD1.5/animatediff",
"description": "AnimateDiff SparseCtrl RGB ControlNet model",
"reference": "https://huggingface.co/guoyww/animatediff",
"filename": "v3_sd15_sparsectrl_rgb.ckpt",
"url": "https://huggingface.co/guoyww/animatediff/resolve/main/v3_sd15_sparsectrl_rgb.ckpt"
},
{
"name": "animatediff/v3_sd15_sparsectrl_scribble.ckpt",
"type": "controlnet",
"base": "SD1.x",
"save_path": "controlnet/SD1.5/animatediff",
"description": "AnimateDiff SparseCtrl Scribble ControlNet model",
"reference": "https://huggingface.co/guoyww/animatediff",
"filename": "v3_sd15_sparsectrl_scribble.ckpt",
"url": "https://huggingface.co/guoyww/animatediff/resolve/main/v3_sd15_sparsectrl_scribble.ckpt"
},
{
"name": "animatediff/v3_sd15_mm.ckpt (ComfyUI-AnimateDiff-Evolved)",
"type": "animatediff",
"base": "SD1.x",
"save_path": "custom_nodes/ComfyUI-AnimateDiff-Evolved/models",
"description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node. (Note: Requires ComfyUI-Manager V0.24 or above)",
"reference": "https://huggingface.co/guoyww/animatediff",
"filename": "v3_sd15_mm.ckpt",
"url": "https://huggingface.co/guoyww/animatediff/resolve/main/v3_sd15_mm.ckpt"
},
{
"name": "animatediff/v3_sd15_adapter.ckpt",
"type": "lora",
"base": "SD1.x",
"save_path": "loras/SD1.5/animatediff",
"description": "AnimateDiff Adapter LoRA (SD1.5)",
"reference": "https://huggingface.co/guoyww/animatediff",
"filename": "v3_sd15_adapter.ckpt",
"url": "https://huggingface.co/guoyww/animatediff/resolve/main/v3_sd15_adapter.ckpt"
},
{
"name": "Segmind-Vega",
"type": "checkpoints",
"base": "segmind-vega",
"save_path": "checkpoints/segmind-vega",
"description": "The Segmind-Vega Model is a distilled version of the Stable Diffusion XL (SDXL), offering a remarkable 70% reduction in size and an impressive 100% speedup while retaining high-quality text-to-image generation capabilities.",
"reference": "https://huggingface.co/segmind/Segmind-Vega",
"filename": "segmind-vega.safetensors",
"url": "https://huggingface.co/segmind/Segmind-Vega/resolve/main/segmind-vega.safetensors"
},
{
"name": "Segmind-VegaRT - Latent Consistency Model (LCM) LoRA of Segmind-Vega",
"type": "lora",
"base": "segmind-vega",
"save_path": "loras/segmind-vega",
"description": "Segmind-VegaRT a distilled consistency adapter for Segmind-Vega that allows to reduce the number of inference steps to only between 2 - 8 steps.",
"reference": "https://huggingface.co/segmind/Segmind-VegaRT",
"filename": "pytorch_lora_weights.safetensors",
"url": "https://huggingface.co/segmind/Segmind-VegaRT/resolve/main/pytorch_lora_weights.safetensors"
},
{
"name": "stabilityai/Stable Zero123",
"type": "zero123",
"base": "zero123",
"save_path": "checkpoints/zero123",
"description": "Stable Zero123 is a model for view-conditioned image generation based on [a/Zero123](https://github.com/cvlab-columbia/zero123).",
"reference": "https://huggingface.co/stabilityai/stable-zero123",
"filename": "stable_zero123.ckpt",
"url": "https://huggingface.co/stabilityai/stable-zero123/resolve/main/stable_zero123.ckpt"
},
{
"name": "LongAnimatediff/lt_long_mm_32_frames.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)",
"type": "animatediff",
"base": "SD1.x",
"save_path": "animatediff_models",
"description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.",
"reference": "https://huggingface.co/Lightricks/LongAnimateDiff",
"filename": "lt_long_mm_32_frames.ckpt",
"url": "https://huggingface.co/Lightricks/LongAnimateDiff/resolve/main/lt_long_mm_32_frames.ckpt"
},
{
"name": "LongAnimatediff/lt_long_mm_16_64_frames.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)",
"type": "animatediff",
"base": "SD1.x",
"save_path": "animatediff_models",
"description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.",
"reference": "https://huggingface.co/Lightricks/LongAnimateDiff",
"filename": "lt_long_mm_16_64_frames.ckpt",
"url": "https://huggingface.co/Lightricks/LongAnimateDiff/resolve/main/lt_long_mm_16_64_frames.ckpt"
},
{
"name": "ip-adapter_sd15.safetensors",
"type": "IP-Adapter",
"base": "SD1.5",
"save_path": "ipadapter",
"description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.",
"reference": "https://huggingface.co/h94/IP-Adapter",
"filename": "ip-adapter_sd15.safetensors",
"url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter_sd15.safetensors"
},
{
"name": "ip-adapter_sd15_light.safetensors",
"type": "IP-Adapter",
"base": "SD1.5",
"save_path": "ipadapter",
"description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.",
"reference": "https://huggingface.co/h94/IP-Adapter",
"filename": "ip-adapter_sd15_light.safetensors",
"url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter_sd15_light.safetensors"
},
{
"name": "ip-adapter_sd15_vit-G.safetensors",
"type": "IP-Adapter",
"base": "SD1.5",
"save_path": "ipadapter",
"description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.",
"reference": "https://huggingface.co/h94/IP-Adapter",
"filename": "ip-adapter_sd15_vit-G.safetensors",
"url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter_sd15_vit-G.safetensors"
},
{
"name": "ip-adapter-plus_sd15.safetensors",
"type": "IP-Adapter",
"base": "SD1.5",
"save_path": "ipadapter",
"description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.",
"reference": "https://huggingface.co/h94/IP-Adapter",
"filename": "ip-adapter-plus_sd15.safetensors",
"url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter-plus_sd15.safetensors"
},
{
"name": "ip-adapter-plus-face_sd15.safetensors",
"type": "IP-Adapter",
"base": "SD1.5",
"save_path": "ipadapter",
"description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.",
"reference": "https://huggingface.co/h94/IP-Adapter",
"filename": "ip-adapter-plus-face_sd15.safetensors",
"url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter-plus-face_sd15.safetensors"
},
{
"name": "ip-adapter-full-face_sd15.safetensors",
"type": "IP-Adapter",
"base": "SD1.5",
"save_path": "ipadapter",
"description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.",
"reference": "https://huggingface.co/h94/IP-Adapter",
"filename": "ip-adapter-full-face_sd15.safetensors",
"url": "https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter-full-face_sd15.safetensors"
},
{
"name": "ip-adapter_sdxl.safetensors",
"type": "IP-Adapter",
"base": "SDXL",
"save_path": "ipadapter",
"description": "You can use this model in the [a/ComfyUI IPAdapter plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) extension.",
"reference": "https://huggingface.co/h94/IP-Adapter",
"filename": "ip-adapter_sdxl.safetensors",
"url": "https://huggingface.co/h94/IP-Adapter/resolve/main/sdxl_models/ip-adapter_sdxl.safetensors"
},
{
"name": "ip-adapter_sdxl_vit-h.safetensors",
"type": "IP-Adapter",
"base": "SDXL",
"save_path": "ipadapter",
"description": "This model requires the use of the SD1.5 encoder despite being for SDXL checkpoints",
"reference": "https://huggingface.co/h94/IP-Adapter",
"filename": "ip-adapter_sdxl_vit-h.safetensors",
"url": "https://huggingface.co/h94/IP-Adapter/resolve/main/sdxl_models/ip-adapter_sdxl_vit-h.safetensors"
},
{
"name": "ip-adapter-plus_sdxl_vit-h.safetensors",
"type": "IP-Adapter",
"base": "SDXL",
"save_path": "ipadapter",
"description": "This model requires the use of the SD1.5 encoder despite being for SDXL checkpoints",
"reference": "https://huggingface.co/h94/IP-Adapter",
"filename": "ip-adapter-plus_sdxl_vit-h.safetensors",
"url": "https://huggingface.co/h94/IP-Adapter/resolve/main/sdxl_models/ip-adapter-plus_sdxl_vit-h.safetensors"
},
{
"name": "ip-adapter-plus-face_sdxl_vit-h.safetensors",
"type": "IP-Adapter",
"base": "SDXL",
"save_path": "ipadapter",
"description": "This model requires the use of the SD1.5 encoder despite being for SDXL checkpoints",
"reference": "https://huggingface.co/h94/IP-Adapter",
"filename": "ip-adapter-plus-face_sdxl_vit-h.safetensors",
"url": "https://huggingface.co/h94/IP-Adapter/resolve/main/sdxl_models/ip-adapter-plus-face_sdxl_vit-h.safetensors"
},
{
"name": "SDXL-Turbo 1.0 (fp16)",
"type": "checkpoints",
"base": "SDXL",
"save_path": "checkpoints/SDXL-TURBO",
"description": "[6.9GB] SDXL-Turbo 1.0 fp16",
"reference": "https://huggingface.co/stabilityai/sdxl-turbo",
"filename": "sd_xl_turbo_1.0_fp16.safetensors",
"url": "https://huggingface.co/stabilityai/sdxl-turbo/resolve/main/sd_xl_turbo_1.0_fp16.safetensors"
},
{
"name": "SDXL-Turbo 1.0",
"type": "checkpoints",
"base": "SDXL",
"save_path": "checkpoints/SDXL-TURBO",
"description": "[13.9GB] SDXL-Turbo 1.0",
"reference": "https://huggingface.co/stabilityai/sdxl-turbo",
"filename": "sd_xl_turbo_1.0.safetensors",
"url": "https://huggingface.co/stabilityai/sdxl-turbo/resolve/main/sd_xl_turbo_1.0.safetensors"
},
{
"name": "Stable Video Diffusion Image-to-Video",
"type": "checkpoints",
"base": "SVD",
"save_path": "checkpoints/SVD",
"description": "Stable Video Diffusion (SVD) Image-to-Video is a diffusion model that takes in a still image as a conditioning frame, and generates a video from it.\nNOTE: 14 frames @ 576x1024",
"reference": "https://huggingface.co/stabilityai/stable-video-diffusion-img2vid",
"filename": "svd.safetensors",
"url": "https://huggingface.co/stabilityai/stable-video-diffusion-img2vid/resolve/main/svd.safetensors"
},
{
"name": "Stable Video Diffusion Image-to-Video (XT)",
"type": "checkpoints",
"base": "SVD",
"save_path": "checkpoints/SVD",
"description": "Stable Video Diffusion (SVD) Image-to-Video is a diffusion model that takes in a still image as a conditioning frame, and generates a video from it.\nNOTE: 25 frames @ 576x1024 ",
"reference": "https://huggingface.co/stabilityai/stable-video-diffusion-img2vid-xt",
"filename": "svd_xt.safetensors",
"url": "https://huggingface.co/stabilityai/stable-video-diffusion-img2vid-xt/resolve/main/svd_xt.safetensors"
},
{
"name": "animatediff/mm_sdxl_v10_beta.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)",
"type": "animatediff",
"base": "SDXL",
"save_path": "animatediff_models",
"description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.",
"reference": "https://huggingface.co/guoyww/animatediff",
"filename": "mm_sdxl_v10_beta.ckpt",
"url": "https://huggingface.co/guoyww/animatediff/resolve/main/mm_sdxl_v10_beta.ckpt"
},
{
"name": "animatediff/v2_lora_PanLeft.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)",
"type": "motion lora",
"base": "SD1.x",
"save_path": "animatediff_motion_lora",
"description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.",
"reference": "https://huggingface.co/guoyww/animatediff",
"filename": "v2_lora_PanLeft.ckpt",
"url": "https://huggingface.co/guoyww/animatediff/resolve/main/v2_lora_PanLeft.ckpt"
},
{
"name": "animatediff/v2_lora_PanRight.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)",
"type": "motion lora",
"base": "SD1.x",
"save_path": "animatediff_motion_lora",
"description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.",
"reference": "https://huggingface.co/guoyww/animatediff",
"filename": "v2_lora_PanRight.ckpt",
"url": "https://huggingface.co/guoyww/animatediff/resolve/main/v2_lora_PanRight.ckpt"
},
{
"name": "animatediff/v2_lora_RollingAnticlockwise.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)",
"type": "motion lora",
"base": "SD1.x",
"save_path": "animatediff_motion_lora",
"description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.",
"reference": "https://huggingface.co/guoyww/animatediff",
"filename": "v2_lora_RollingAnticlockwise.ckpt",
"url": "https://huggingface.co/guoyww/animatediff/resolve/main/v2_lora_RollingAnticlockwise.ckpt"
},
{
"name": "animatediff/v2_lora_RollingClockwise.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)",
"type": "motion lora",
"base": "SD1.x",
"save_path": "animatediff_motion_lora",
"description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.",
"reference": "https://huggingface.co/guoyww/animatediff",
"filename": "v2_lora_RollingClockwise.ckpt",
"url": "https://huggingface.co/guoyww/animatediff/resolve/main/v2_lora_RollingClockwise.ckpt"
},
{
"name": "animatediff/v2_lora_TiltDown.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)",
"type": "motion lora",
"base": "SD1.x",
"save_path": "animatediff_motion_lora",
"description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.",
"reference": "https://huggingface.co/guoyww/animatediff",
"filename": "v2_lora_TiltDown.ckpt",
"url": "https://huggingface.co/guoyww/animatediff/resolve/main/v2_lora_TiltDown.ckpt"
},
{
"name": "animatediff/v2_lora_TiltUp.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)",
"type": "motion lora",
"base": "SD1.x",
"save_path": "animatediff_motion_lora",
"description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.",
"reference": "https://huggingface.co/guoyww/animatediff",
"filename": "v2_lora_TiltUp.ckpt",
"url": "https://huggingface.co/guoyww/animatediff/resolve/main/v2_lora_TiltUp.ckpt"
},
{
"name": "animatediff/v2_lora_ZoomIn.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)",
"type": "motion lora",
"base": "SD1.x",
"save_path": "animatediff_motion_lora",
"description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.",
"reference": "https://huggingface.co/guoyww/animatediff",
"filename": "v2_lora_ZoomIn.ckpt",
"url": "https://huggingface.co/guoyww/animatediff/resolve/main/v2_lora_ZoomIn.ckpt"
},
{
"name": "animatediff/v2_lora_ZoomOut.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)",
"type": "motion lora",
"base": "SD1.x",
"save_path": "animatediff_motion_lora",
"description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.",
"reference": "https://huggingface.co/guoyww/animatediff",
"filename": "v2_lora_ZoomOut.ckpt",
"url": "https://huggingface.co/guoyww/animatediff/resolve/main/v2_lora_ZoomOut.ckpt"
},
{
"name": "CiaraRowles/TemporalNet1XL (1.0)",
"type": "controlnet",
"base": "SD1.5",
"save_path": "controlnet/TemporalNet1XL",
"description": "This is TemporalNet1XL, it is a re-train of the controlnet TemporalNet1 with Stable Diffusion XL.",
"reference": "https://huggingface.co/CiaraRowles/controlnet-temporalnet-sdxl-1.0",
"filename": "diffusion_pytorch_model.safetensors",
"url": "https://huggingface.co/CiaraRowles/controlnet-temporalnet-sdxl-1.0/resolve/main/diffusion_pytorch_model.safetensors"
},
{
"name": "LCM LoRA SD1.5",
"type": "lora",
"base": "SD1.5",
"save_path": "loras/lcm/SD1.5",
"description": "Latent Consistency LoRA for SD1.5",
"reference": "https://huggingface.co/latent-consistency/lcm-lora-sdv1-5",
"filename": "pytorch_lora_weights.safetensors",
"url": "https://huggingface.co/latent-consistency/lcm-lora-sdv1-5/resolve/main/pytorch_lora_weights.safetensors"
},
{
"name": "LCM LoRA SSD-1B",
"type": "lora",
"base": "SSD-1B",
"save_path": "loras/lcm/SSD-1B",
"description": "Latent Consistency LoRA for SSD-1B",
"reference": "https://huggingface.co/latent-consistency/lcm-lora-ssd-1b",
"filename": "pytorch_lora_weights.safetensors",
"url": "https://huggingface.co/latent-consistency/lcm-lora-ssd-1b/resolve/main/pytorch_lora_weights.safetensors"
},
{
"name": "LCM LoRA SDXL",
"type": "lora",
"base": "SSD-1B",
"save_path": "loras/lcm/SDXL",
"description": "Latent Consistency LoRA for SDXL",
"reference": "https://huggingface.co/latent-consistency/lcm-lora-sdxl",
"filename": "pytorch_lora_weights.safetensors",
"url": "https://huggingface.co/latent-consistency/lcm-lora-sdxl/resolve/main/pytorch_lora_weights.safetensors"
},
{
"name": "face_yolov8m-seg_60.pt (segm)",
"type": "Ultralytics",
"base": "Ultralytics",
"save_path": "ultralytics/segm",
"description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.",
"reference": "https://github.com/hben35096/assets/releases/tag/yolo8",
"filename": "face_yolov8m-seg_60.pt",
"url": "https://github.com/hben35096/assets/releases/download/yolo8/face_yolov8m-seg_60.pt"
},
{
"name": "face_yolov8n-seg2_60.pt (segm)",
"type": "Ultralytics",
"base": "Ultralytics",
"save_path": "ultralytics/segm",
"description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.",
"reference": "https://github.com/hben35096/assets/releases/tag/yolo8",
"filename": "face_yolov8n-seg2_60.pt",
"url": "https://github.com/hben35096/assets/releases/download/yolo8/face_yolov8n-seg2_60.pt"
},
{
"name": "hair_yolov8n-seg_60.pt (segm)",
"type": "Ultralytics",
"base": "Ultralytics",
"save_path": "ultralytics/segm",
"description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.",
"reference": "https://github.com/hben35096/assets/releases/tag/yolo8",
"filename": "hair_yolov8n-seg_60.pt",
"url": "https://github.com/hben35096/assets/releases/download/yolo8/hair_yolov8n-seg_60.pt"
},
{
"name": "skin_yolov8m-seg_400.pt (segm)",
"type": "Ultralytics",
"base": "Ultralytics",
"save_path": "ultralytics/segm",
"description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.",
"reference": "https://github.com/hben35096/assets/releases/tag/yolo8",
"filename": "skin_yolov8m-seg_400.pt",
"url": "https://github.com/hben35096/assets/releases/download/yolo8/skin_yolov8m-seg_400.pt"
},
{
"name": "skin_yolov8n-seg_400.pt (segm)",
"type": "Ultralytics",
"base": "Ultralytics",
"save_path": "ultralytics/segm",
"description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.",
"reference": "https://github.com/hben35096/assets/releases/tag/yolo8",
"filename": "skin_yolov8n-seg_400.pt",
"url": "https://github.com/hben35096/assets/releases/download/yolo8/skin_yolov8n-seg_400.pt"
},
{
"name": "skin_yolov8n-seg_800.pt (segm)",
"type": "Ultralytics",
"base": "Ultralytics",
"save_path": "ultralytics/segm",
"description": "These are the available models in the UltralyticsDetectorProvider of Impact Pack.",
"reference": "https://github.com/hben35096/assets/releases/tag/yolo8",
"filename": "skin_yolov8n-seg_800.pt",
"url": "https://github.com/hben35096/assets/releases/download/yolo8/skin_yolov8n-seg_800.pt"
},
{
"name": "CiaraRowles/temporaldiff-v1-animatediff.ckpt (ComfyUI-AnimateDiff-Evolved) (Updated path)",
"type": "animatediff",
"base": "SD1.x",
"save_path": "animatediff_models",
"description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.",
"reference": "https://huggingface.co/CiaraRowles/TemporalDiff",
"filename": "temporaldiff-v1-animatediff.ckpt",
"url": "https://huggingface.co/CiaraRowles/TemporalDiff/resolve/main/temporaldiff-v1-animatediff.ckpt"
},
{
"name": "animatediff/mm_sd_v15_v2.ckpt (ComfyUI-AnimateDiff-Evolved)",
"type": "animatediff",
"base": "SD1.x",
"save_path": "custom_nodes/ComfyUI-AnimateDiff-Evolved/models",
"description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node. (Note: Requires ComfyUI-Manager V0.24 or above)",
"reference": "https://huggingface.co/guoyww/animatediff",
"filename": "mm_sd_v15_v2.ckpt",
"url": "https://huggingface.co/guoyww/animatediff/resolve/main/mm_sd_v15_v2.ckpt"
},
{
"name": "AD_Stabilized_Motion/mm-Stabilized_high.pth (ComfyUI-AnimateDiff-Evolved) (Updated path)",
"type": "animatediff",
"base": "SD1.x",
"save_path": "animatediff_models",
"description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.",
"reference": "https://huggingface.co/manshoety/AD_Stabilized_Motion",
"filename": "mm-Stabilized_high.pth",
"url": "https://huggingface.co/manshoety/AD_Stabilized_Motion/resolve/main/mm-Stabilized_high.pth"
},
{
"name": "AD_Stabilized_Motion/mm-Stabilized_mid.pth (ComfyUI-AnimateDiff-Evolved) (Updated path)",
"type": "animatediff",
"base": "SD1.x",
"save_path": "animatediff_models",
"description": "Pressing 'install' directly downloads the model from the Kosinkadink/ComfyUI-AnimateDiff-Evolved extension node.",
"reference": "https://huggingface.co/manshoety/AD_Stabilized_Motion",
"filename": "mm-Stabilized_mid.pth",
"url": "https://huggingface.co/manshoety/AD_Stabilized_Motion/resolve/main/mm-Stabilized_mid.pth"
} }
] ]
} }

90
node_db/tutorial/custom-node-list.json

@ -10,36 +10,6 @@
"install_type": "git-clone", "install_type": "git-clone",
"description": "There is a small node pack attached to this guide. This includes the init file and 3 nodes associated with the tutorials." "description": "There is a small node pack attached to this guide. This includes the init file and 3 nodes associated with the tutorials."
}, },
{
"author": "bamboodia",
"title": "BAM Nodes",
"reference": "https://github.com/bamboodia/BAM_Nodes",
"files": [
"https://github.com/bamboodia/BAM_Nodes"
],
"install_type": "git-clone",
"description": "A collection of comfyui nodes that I have made for nothing more than educational purposes."
},
{
"author": "BadCafeCode",
"title": "execution-inversion-demo-comfyui",
"reference": "https://github.com/BadCafeCode/execution-inversion-demo-comfyui",
"files": [
"https://github.com/BadCafeCode/execution-inversion-demo-comfyui"
],
"install_type": "git-clone",
"description": "These are demo nodes for [a/PR2666](https://github.com/comfyanonymous/ComfyUI/pull/2666)"
},
{
"author": "ecjojo",
"title": "ecjojo_example_nodes",
"reference": "https://github.com/ecjojo/ecjojo-example-nodes",
"files": [
"https://github.com/ecjojo/ecjojo-example-nodes"
],
"install_type": "git-clone",
"description": "Welcome to ecjojo_example_nodes! This example is specifically designed for beginners who want to learn how to write a simple custom node.\nFeel free to modify this example and make it your own. Experiment with different features and functionalities to enhance your understanding of ComfyUI custom nodes. Don't be afraid to explore and customize the code to suit your needs.\nBy diving into this example and making it your own, you'll gain valuable hands-on experience in creating custom nodes in ComfyUI. Enjoy the process of learning and have fun with your custom node development journey!"
},
{ {
"author": "dynamixar", "author": "dynamixar",
"title": "Atluris", "title": "Atluris",
@ -80,6 +50,16 @@
"install_type": "git-clone", "install_type": "git-clone",
"description": "Tutorial nodes" "description": "Tutorial nodes"
}, },
{
"author": "GraftingRayman",
"title": "ComfyUI-Trajectory",
"reference": "https://github.com/GraftingRayman/ComfyUI-Trajectory",
"files": [
"https://github.com/GraftingRayman/ComfyUI-Trajectory"
],
"install_type": "git-clone",
"description": "Nodes:GR Trajectory"
},
{ {
"author": "wailovet", "author": "wailovet",
"title": "ComfyUI-WW", "title": "ComfyUI-WW",
@ -139,56 +119,6 @@
], ],
"install_type": "git-clone", "install_type": "git-clone",
"description": "Nodes:M_Layer, M_Output" "description": "Nodes:M_Layer, M_Output"
},
{
"author": "andrewharp",
"title": "ComfyUI Function Annotator",
"reference": "https://github.com/andrewharp/ComfyUI-Annotations",
"files": [
"https://github.com/andrewharp/ComfyUI-Annotations"
],
"install_type": "git-clone",
"description": "This module provides an annotation @ComfyFunc to streamline adding custom node types in ComfyUI. It processes your function's signature to create a wrapped function and custom node definition required for ComfyUI, eliminating all the boilerplate code. In most cases you can just add a @ComfyFunc(\"category\") annotation to your existing function."
},
{
"author": "MokkaBoss1",
"title": "Woman_in_a_dress",
"reference": "https://github.com/MokkaBoss1/Woman_in_a_dress",
"files": [
"https://github.com/MokkaBoss1/Woman_in_a_dress/raw/main/Woman_In_A_Dress.py"
],
"install_type": "git-clone",
"description": "Nodes:Woman_in_a_dress"
},
{
"author": "shinich39",
"title": "comfyui-concat-text-39",
"reference": "https://github.com/shinich39/comfyui-concat-text-39",
"files": [
"https://github.com/shinich39/comfyui-concat-text-39"
],
"install_type": "git-clone",
"description": "Nodes:Concatenate multiple text nodes."
},
{
"author": "nilor-corp",
"title": "nilor-nodes",
"reference": "https://github.com/nilor-corp/nilor-nodes",
"files": [
"https://github.com/nilor-corp/nilor-nodes"
],
"install_type": "git-clone",
"description": "Custom utility nodes for ComfyUI"
},
{
"author": "nilor-corp",
"title": "nilor-nodes",
"reference": "https://github.com/nilor-corp/nilor-nodes",
"files": [
"https://github.com/nilor-corp/nilor-nodes"
],
"install_type": "git-clone",
"description": "Nodes:Nilor Floats, Nilor Int To List Of Bools, Nilor Bool From List Of Bools, Nilor Int From List Of Ints, Nilor List of Ints, Nilor Count Images In Directory"
} }
] ]
} }

28
notebooks/comfyui_colab_with_manager.ipynb

@ -50,21 +50,11 @@
"\n", "\n",
"if OPTIONS['UPDATE_COMFY_UI']:\n", "if OPTIONS['UPDATE_COMFY_UI']:\n",
" !echo -= Updating ComfyUI =-\n", " !echo -= Updating ComfyUI =-\n",
"\n",
" # Correction of the issue of permissions being deleted on Google Drive.\n",
" ![ -f \".ci/nightly/update_windows/update_comfyui_and_python_dependencies.bat\" ] && chmod 755 .ci/nightly/update_windows/update_comfyui_and_python_dependencies.bat\n",
" ![ -f \".ci/nightly/windows_base_files/run_nvidia_gpu.bat\" ] && chmod 755 .ci/nightly/windows_base_files/run_nvidia_gpu.bat\n",
" ![ -f \".ci/update_windows/update_comfyui_and_python_dependencies.bat\" ] && chmod 755 .ci/update_windows/update_comfyui_and_python_dependencies.bat\n",
" ![ -f \".ci/update_windows_cu118/update_comfyui_and_python_dependencies.bat\" ] && chmod 755 .ci/update_windows_cu118/update_comfyui_and_python_dependencies.bat\n",
" ![ -f \".ci/update_windows/update.py\" ] && chmod 755 .ci/update_windows/update.py\n",
" ![ -f \".ci/update_windows/update_comfyui.bat\" ] && chmod 755 .ci/update_windows/update_comfyui.bat\n",
" ![ -f \".ci/update_windows/README_VERY_IMPORTANT.txt\" ] && chmod 755 .ci/update_windows/README_VERY_IMPORTANT.txt\n",
" ![ -f \".ci/update_windows/run_cpu.bat\" ] && chmod 755 .ci/update_windows/run_cpu.bat\n",
" ![ -f \".ci/update_windows/run_nvidia_gpu.bat\" ] && chmod 755 .ci/update_windows/run_nvidia_gpu.bat\n",
"\n",
" !git pull\n", " !git pull\n",
"\n", "\n",
"!echo -= Install dependencies =-\n", "!echo -= Install dependencies =-\n",
"#Remove cu121 as it causes issues in Colab.\n",
"#!pip install xformers!=0.0.18 -r requirements.txt --extra-index-url https://download.pytorch.org/whl/cu121 --extra-index-url https://download.pytorch.org/whl/cu118 --extra-index-url https://download.pytorch.org/whl/cu117\n",
"!pip3 install accelerate\n", "!pip3 install accelerate\n",
"!pip3 install einops transformers>=4.25.1 safetensors>=0.3.0 aiohttp pyyaml Pillow scipy tqdm psutil\n", "!pip3 install einops transformers>=4.25.1 safetensors>=0.3.0 aiohttp pyyaml Pillow scipy tqdm psutil\n",
"!pip3 install xformers!=0.0.18 torch==2.1.0 torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121\n", "!pip3 install xformers!=0.0.18 torch==2.1.0 torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121\n",
@ -72,14 +62,6 @@
"\n", "\n",
"if OPTIONS['USE_COMFYUI_MANAGER']:\n", "if OPTIONS['USE_COMFYUI_MANAGER']:\n",
" %cd custom_nodes\n", " %cd custom_nodes\n",
"\n",
" # Correction of the issue of permissions being deleted on Google Drive.\n",
" ![ -f \"ComfyUI-Manager/check.sh\" ] && chmod 755 ComfyUI-Manager/check.sh\n",
" ![ -f \"ComfyUI-Manager/scan.sh\" ] && chmod 755 ComfyUI-Manager/scan.sh\n",
" ![ -f \"ComfyUI-Manager/node_db/dev/scan.sh\" ] && chmod 755 ComfyUI-Manager/node_db/dev/scan.sh\n",
" ![ -f \"ComfyUI-Manager/scripts/install-comfyui-venv-linux.sh\" ] && chmod 755 ComfyUI-Manager/scripts/install-comfyui-venv-linux.sh\n",
" ![ -f \"ComfyUI-Manager/scripts/install-comfyui-venv-win.bat\" ] && chmod 755 ComfyUI-Manager/scripts/install-comfyui-venv-win.bat\n",
"\n",
" ![ ! -d ComfyUI-Manager ] && echo -= Initial setup ComfyUI-Manager =- && git clone https://github.com/ltdrdata/ComfyUI-Manager\n", " ![ ! -d ComfyUI-Manager ] && echo -= Initial setup ComfyUI-Manager =- && git clone https://github.com/ltdrdata/ComfyUI-Manager\n",
" %cd ComfyUI-Manager\n", " %cd ComfyUI-Manager\n",
" !git pull\n", " !git pull\n",
@ -87,9 +69,9 @@
"%cd $WORKSPACE\n", "%cd $WORKSPACE\n",
"\n", "\n",
"if OPTIONS['INSTALL_CUSTOM_NODES_DEPENDENCIES']:\n", "if OPTIONS['INSTALL_CUSTOM_NODES_DEPENDENCIES']:\n",
" !pwd\n",
" !echo -= Install custom nodes dependencies =-\n", " !echo -= Install custom nodes dependencies =-\n",
" !pip install GitPython\n", " ![ -f \"custom_nodes/ComfyUI-Manager/scripts/colab-dependencies.py\" ] && python \"custom_nodes/ComfyUI-Manager/scripts/colab-dependencies.py\"\n"
" !python custom_nodes/ComfyUI-Manager/cm-cli.py restore-dependencies\n"
] ]
}, },
{ {
@ -368,4 +350,4 @@
}, },
"nbformat": 4, "nbformat": 4,
"nbformat_minor": 0 "nbformat_minor": 0
} }

21
pip_overrides.json.template

@ -1,21 +0,0 @@
{
"imageio-ffmpeg": "imageio",
"imageio[ffmpeg]": "imageio",
"imageio_ffmpeg": "imageio",
"diffusers~=0.21.4": "diffusers",
"huggingface_hub": "huggingface-hub",
"numpy<1.24>=1.18": "numpy",
"numpy>=1.18.5, <1.25.0": "numpy",
"opencv-contrib-python": "opencv-contrib-python-headless",
"opencv-python": "opencv-contrib-python-headless",
"opencv-python-headless": "opencv-contrib-python-headless",
"opencv-python-headless[ffmpeg]<=4.7.0.72": "opencv-contrib-python-headless",
"opencv-python>=4.7.0.72": "opencv-contrib-python-headless",
"pandas<=1.5.1": "pandas",
"scikit-image==0.20.0": "scikit-image",
"scipy>=1.11.4": "scipy",
"segment_anything": "segment-anything",
"timm==0.6.5": "timm",
"timm>=0.4.12": "timm",
"transformers==4.26.1": "transformers"
}

203
prestartup_script.py

@ -7,24 +7,15 @@ import threading
import re import re
import locale import locale
import platform import platform
import json
glob_path = os.path.join(os.path.dirname(__file__), "glob") glob_path = os.path.join(os.path.dirname(__file__), "glob")
sys.path.append(glob_path) sys.path.append(glob_path)
from manager_util import *
import cm_global import cm_global
cm_global.pip_downgrade_blacklist = ['torch', 'torchsde', 'torchvision', 'transformers', 'safetensors', 'kornia'] message_collapses = []
def skip_pip_spam(x):
return ('Requirement already satisfied:' in x) or ("DEPRECATION: Loading egg at" in x)
message_collapses = [skip_pip_spam]
import_failed_extensions = set() import_failed_extensions = set()
cm_global.variables['cm.on_revision_detected_handler'] = [] cm_global.variables['cm.on_revision_detected_handler'] = []
enable_file_logging = True enable_file_logging = True
@ -69,23 +60,6 @@ custom_nodes_path = os.path.abspath(os.path.join(comfyui_manager_path, ".."))
startup_script_path = os.path.join(comfyui_manager_path, "startup-scripts") startup_script_path = os.path.join(comfyui_manager_path, "startup-scripts")
restore_snapshot_path = os.path.join(startup_script_path, "restore-snapshot.json") restore_snapshot_path = os.path.join(startup_script_path, "restore-snapshot.json")
git_script_path = os.path.join(comfyui_manager_path, "git_helper.py") git_script_path = os.path.join(comfyui_manager_path, "git_helper.py")
pip_overrides_path = os.path.join(comfyui_manager_path, "pip_overrides.json")
cm_global.pip_overrides = {}
if os.path.exists(pip_overrides_path):
with open(pip_overrides_path, 'r', encoding="UTF-8", errors="ignore") as json_file:
cm_global.pip_overrides = json.load(json_file)
def remap_pip_package(pkg):
if pkg in cm_global.pip_overrides:
res = cm_global.pip_overrides[pkg]
print(f"[ComfyUI-Manager] '{pkg}' is remapped to '{res}'")
return res
else:
return pkg
std_log_lock = threading.Lock() std_log_lock = threading.Lock()
@ -192,9 +166,11 @@ try:
write_stderr = wrapper_stderr write_stderr = wrapper_stderr
pat_tqdm = r'\d+%.*\[(.*?)\]' pat_tqdm = r'\d+%.*\[(.*?)\]'
pat_import_fail = r'seconds \(IMPORT FAILED\):.*[/\\]custom_nodes[/\\](.*)$' pat_import_fail = r'seconds \(IMPORT FAILED\):'
pat_custom_node = r'[/\\]custom_nodes[/\\](.*)$'
is_start_mode = True is_start_mode = True
is_import_fail_mode = False
class ComfyUIManagerLogger: class ComfyUIManagerLogger:
def __init__(self, is_stdout): def __init__(self, is_stdout):
@ -214,17 +190,26 @@ try:
def write(self, message): def write(self, message):
global is_start_mode global is_start_mode
global is_import_fail_mode
if any(f(message) for f in message_collapses): if any(f(message) for f in message_collapses):
return return
if is_start_mode: if is_start_mode:
match = re.search(pat_import_fail, message) if is_import_fail_mode:
if match: match = re.search(pat_custom_node, message)
import_failed_extensions.add(match.group(1)) if match:
import_failed_extensions.add(match.group(1))
is_import_fail_mode = False
else:
match = re.search(pat_import_fail, message)
if match:
is_import_fail_mode = True
else:
is_import_fail_mode = False
if 'Starting server' in message: if 'Starting server' in message:
is_start_mode = False is_start_mode = False
if not self.is_stdout: if not self.is_stdout:
match = re.search(pat_tqdm, message) match = re.search(pat_tqdm, message)
@ -300,30 +285,6 @@ except Exception as e:
print(f"[ComfyUI-Manager] Logging failed: {e}") print(f"[ComfyUI-Manager] Logging failed: {e}")
try:
import git
except ModuleNotFoundError:
my_path = os.path.dirname(__file__)
requirements_path = os.path.join(my_path, "requirements.txt")
print(f"## ComfyUI-Manager: installing dependencies. (GitPython)")
try:
result = subprocess.check_output([sys.executable, '-s', '-m', 'pip', 'install', '-r', requirements_path])
except subprocess.CalledProcessError as e:
print(f"## [ERROR] ComfyUI-Manager: Attempting to reinstall dependencies using an alternative method.")
try:
result = subprocess.check_output([sys.executable, '-s', '-m', 'pip', 'install', '--user', '-r', requirements_path])
except subprocess.CalledProcessError as e:
print(f"## [ERROR] ComfyUI-Manager: Failed to install the GitPython package in the correct Python environment. Please install it manually in the appropriate environment. (You can seek help at https://app.element.io/#/room/%23comfyui_space%3Amatrix.org)")
try:
import git
print(f"## ComfyUI-Manager: installing dependencies done.")
except:
# maybe we should sys.exit() here? there is at least two screens worth of error messages still being pumped after our error messages
print(f"## [ERROR] ComfyUI-Manager: GitPython package seems to be installed, but failed to load somehow. Make sure you have a working git client installed")
print("** ComfyUI startup time:", datetime.datetime.now()) print("** ComfyUI startup time:", datetime.datetime.now())
print("** Platform:", platform.system()) print("** Platform:", platform.system())
print("** Python version:", sys.version) print("** Python version:", sys.version)
@ -335,26 +296,6 @@ else:
print("** Log path: file logging is disabled") print("** Log path: file logging is disabled")
def read_downgrade_blacklist():
try:
import configparser
config_path = os.path.join(os.path.dirname(__file__), "config.ini")
config = configparser.ConfigParser()
config.read(config_path)
default_conf = config['default']
if 'downgrade_blacklist' in default_conf:
items = default_conf['downgrade_blacklist'].split(',')
items = [x.strip() for x in items if x != '']
cm_global.pip_downgrade_blacklist += items
cm_global.pip_downgrade_blacklist = list(set(cm_global.pip_downgrade_blacklist))
except:
pass
read_downgrade_blacklist()
def check_bypass_ssl(): def check_bypass_ssl():
try: try:
import configparser import configparser
@ -377,30 +318,21 @@ check_bypass_ssl()
# Perform install # Perform install
processed_install = set() processed_install = set()
script_list_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "startup-scripts", "install-scripts.txt") script_list_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "startup-scripts", "install-scripts.txt")
pip_map = None pip_list = None
def get_installed_packages(): def get_installed_packages():
global pip_map global pip_list
if pip_map is None: if pip_list is None:
try: try:
result = subprocess.check_output([sys.executable, '-m', 'pip', 'list'], universal_newlines=True) result = subprocess.check_output([sys.executable, '-m', 'pip', 'list'], universal_newlines=True)
pip_list = set([line.split()[0].lower() for line in result.split('\n') if line.strip()])
pip_map = {}
for line in result.split('\n'):
x = line.strip()
if x:
y = line.split()
if y[0] == 'Package' or y[0].startswith('-'):
continue
pip_map[y[0]] = y[1]
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
print(f"[ComfyUI-Manager] Failed to retrieve the information of installed pip packages.") print(f"[ComfyUI-Manager] Failed to retrieve the information of installed pip packages.")
return set() return set()
return pip_map return pip_list
def is_installed(name): def is_installed(name):
@ -409,29 +341,19 @@ def is_installed(name):
if name.startswith('#'): if name.startswith('#'):
return True return True
pattern = r'([^<>!=]+)([<>!=]=?)(.*)' pattern = r'([^<>!=]+)([<>!=]=?)'
match = re.search(pattern, name) match = re.search(pattern, name)
if match: if match:
name = match.group(1) name = match.group(1)
if name in cm_global.pip_downgrade_blacklist:
pips = get_installed_packages()
if match is None:
if name in pips:
return True
elif match.group(2) in ['<=', '==', '<']:
if name in pips:
if StrictVersion(pips[name]) >= StrictVersion(match.group(3)):
print(f"[ComfyUI-Manager] skip black listed pip installation: '{name}'")
return True
return name.lower() in get_installed_packages() return name.lower() in get_installed_packages()
if os.path.exists(restore_snapshot_path): if os.path.exists(restore_snapshot_path):
try: try:
import json
cloned_repos = [] cloned_repos = []
def msg_capture(stream, prefix): def msg_capture(stream, prefix):
@ -459,39 +381,40 @@ if os.path.exists(restore_snapshot_path):
cmd_str = [sys.executable, git_script_path, '--apply-snapshot', restore_snapshot_path] cmd_str = [sys.executable, git_script_path, '--apply-snapshot', restore_snapshot_path]
exit_code = process_wrap(cmd_str, custom_nodes_path, handler=msg_capture) exit_code = process_wrap(cmd_str, custom_nodes_path, handler=msg_capture)
repository_name = '' with open(restore_snapshot_path, 'r', encoding="UTF-8", errors="ignore") as json_file:
for url in cloned_repos: info = json.load(json_file)
try: for url in cloned_repos:
repository_name = url.split("/")[-1].strip() try:
repo_path = os.path.join(custom_nodes_path, repository_name) repository_name = url.split("/")[-1].strip()
repo_path = os.path.abspath(repo_path) repo_path = os.path.join(custom_nodes_path, repository_name)
repo_path = os.path.abspath(repo_path)
requirements_path = os.path.join(repo_path, 'requirements.txt')
install_script_path = os.path.join(repo_path, 'install.py') requirements_path = os.path.join(repo_path, 'requirements.txt')
install_script_path = os.path.join(repo_path, 'install.py')
this_exit_code = 0
this_exit_code = 0
if os.path.exists(requirements_path):
with open(requirements_path, 'r', encoding="UTF-8", errors="ignore") as file: if os.path.exists(requirements_path):
for line in file: with open(requirements_path, 'r', encoding="UTF-8", errors="ignore") as file:
package_name = remap_pip_package(line.strip()) for line in file:
if package_name and not is_installed(package_name): package_name = line.strip()
install_cmd = [sys.executable, "-m", "pip", "install", package_name] if package_name and not is_installed(package_name):
this_exit_code += process_wrap(install_cmd, repo_path) install_cmd = [sys.executable, "-m", "pip", "install", package_name]
this_exit_code += process_wrap(install_cmd, repo_path)
if os.path.exists(install_script_path) and f'{repo_path}/install.py' not in processed_install:
processed_install.add(f'{repo_path}/install.py') if os.path.exists(install_script_path) and f'{repo_path}/install.py' not in processed_install:
install_cmd = [sys.executable, install_script_path] processed_install.add(f'{repo_path}/install.py')
print(f">>> {install_cmd} / {repo_path}") install_cmd = [sys.executable, install_script_path]
this_exit_code += process_wrap(install_cmd, repo_path) print(f">>> {install_cmd} / {repo_path}")
this_exit_code += process_wrap(install_cmd, repo_path)
if this_exit_code != 0:
if this_exit_code != 0:
print(f"[ComfyUI-Manager] Restoring '{repository_name}' is failed.")
except Exception as e:
print(e)
print(f"[ComfyUI-Manager] Restoring '{repository_name}' is failed.") print(f"[ComfyUI-Manager] Restoring '{repository_name}' is failed.")
except Exception as e:
print(e)
print(f"[ComfyUI-Manager] Restoring '{repository_name}' is failed.")
if exit_code != 0: if exit_code != 0:
print(f"[ComfyUI-Manager] Restore snapshot failed.") print(f"[ComfyUI-Manager] Restore snapshot failed.")
else: else:
@ -514,7 +437,7 @@ def execute_lazy_install_script(repo_path, executable):
print(f"Install: pip packages for '{repo_path}'") print(f"Install: pip packages for '{repo_path}'")
with open(requirements_path, "r") as requirements_file: with open(requirements_path, "r") as requirements_file:
for line in requirements_file: for line in requirements_file:
package_name = remap_pip_package(line.strip()) package_name = line.strip()
if package_name and not is_installed(package_name): if package_name and not is_installed(package_name):
install_cmd = [executable, "-m", "pip", "install", package_name] install_cmd = [executable, "-m", "pip", "install", package_name]
process_wrap(install_cmd, repo_path) process_wrap(install_cmd, repo_path)
@ -575,7 +498,7 @@ if os.path.exists(script_list_path):
print("#######################################################################\n") print("#######################################################################\n")
del processed_install del processed_install
del pip_map del pip_list
def check_windows_event_loop_policy(): def check_windows_event_loop_policy():

6
requirements.txt

@ -1,8 +1,4 @@
GitPython GitPython
PyGithub
matrix-client==0.4.0 matrix-client==0.4.0
transformers transformers
huggingface-hub>0.20 huggingface-hub>0.20
typer
rich
typing-extensions

2
scan.sh

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
rm ~/.tmp/default/*.py > /dev/null 2>&1 rm ~/.tmp/default/*.py > /dev/null 2>&1
python scanner.py ~/.tmp/default $* python scanner.py ~/.tmp/default
cp extension-node-map.json node_db/new/. cp extension-node-map.json node_db/new/.
echo Integrity check echo Integrity check

216
scanner.py

@ -5,15 +5,11 @@ import json
from git import Repo from git import Repo
from torchvision.datasets.utils import download_url from torchvision.datasets.utils import download_url
import concurrent import concurrent
import datetime
builtin_nodes = set() builtin_nodes = set()
import sys import sys
from urllib.parse import urlparse
from github import Github
# prepare temp dir # prepare temp dir
if len(sys.argv) > 1: if len(sys.argv) > 1:
@ -24,49 +20,24 @@ else:
if not os.path.exists(temp_dir): if not os.path.exists(temp_dir):
os.makedirs(temp_dir) os.makedirs(temp_dir)
skip_update = '--skip-update' in sys.argv or '--skip-all' in sys.argv
skip_stat_update = '--skip-stat-update' in sys.argv or '--skip-all' in sys.argv
if not skip_stat_update:
g = Github(os.environ.get('GITHUB_TOKEN'))
else:
g = None
print(f"TEMP DIR: {temp_dir}") print(f"TEMP DIR: {temp_dir}")
parse_cnt = 0
def extract_nodes(code_text): def extract_nodes(code_text):
global parse_cnt
try: try:
if parse_cnt % 100 == 0:
print(f".", end="", flush=True)
parse_cnt += 1
code_text = re.sub(r'\\[^"\']', '', code_text)
parsed_code = ast.parse(code_text) parsed_code = ast.parse(code_text)
assignments = (node for node in parsed_code.body if isinstance(node, ast.Assign)) assignments = (node for node in parsed_code.body if isinstance(node, ast.Assign))
for assignment in assignments: for assignment in assignments:
if isinstance(assignment.targets[0], ast.Name) and assignment.targets[0].id in ['NODE_CONFIG', 'NODE_CLASS_MAPPINGS']: if isinstance(assignment.targets[0], ast.Name) and assignment.targets[0].id == 'NODE_CLASS_MAPPINGS':
node_class_mappings = assignment.value node_class_mappings = assignment.value
break break
else: else:
node_class_mappings = None node_class_mappings = None
if node_class_mappings: if node_class_mappings:
s = set() s = set([key.s.strip() for key in node_class_mappings.keys if key is not None])
for key in node_class_mappings.keys:
if key is not None and isinstance(key.value, str):
s.add(key.value.strip())
return s return s
else: else:
return set() return set()
@ -93,24 +64,15 @@ def scan_in_file(filename, is_builtin=False):
nodes |= extract_nodes(code) nodes |= extract_nodes(code)
def extract_keys(pattern, code): pattern2 = r'^[^=]*_CLASS_MAPPINGS\["(.*?)"\]'
keys = re.findall(pattern, code) keys = re.findall(pattern2, code)
return {key.strip() for key in keys} for key in keys:
nodes.add(key.strip())
def update_nodes(nodes, new_keys):
nodes |= new_keys
patterns = [
r'^[^=]*_CLASS_MAPPINGS\["(.*?)"\]',
r'^[^=]*_CLASS_MAPPINGS\[\'(.*?)\'\]',
r'@register_node\("(.+)",\s*\".+"\)',
r'"(\w+)"\s*:\s*{"class":\s*\w+\s*'
]
with concurrent.futures.ThreadPoolExecutor() as executor: pattern3 = r'^[^=]*_CLASS_MAPPINGS\[\'(.*?)\'\]'
futures = {executor.submit(extract_keys, pattern, code): pattern for pattern in patterns} keys = re.findall(pattern3, code)
for future in concurrent.futures.as_completed(futures): for key in keys:
update_nodes(nodes, future.result()) nodes.add(key.strip())
matches = regex.findall(code) matches = regex.findall(code)
for match in matches: for match in matches:
@ -197,9 +159,9 @@ def get_git_urls_from_json(json_file):
if node.get('install_type') == 'git-clone': if node.get('install_type') == 'git-clone':
files = node.get('files', []) files = node.get('files', [])
if files: if files:
git_clone_files.append((files[0], node.get('title'), node.get('preemptions'), node.get('nodename_pattern'))) git_clone_files.append((files[0], node.get('title'), node.get('nodename_pattern')))
git_clone_files.append(("https://github.com/comfyanonymous/ComfyUI", "ComfyUI", None, None)) git_clone_files.append(("https://github.com/comfyanonymous/ComfyUI", "ComfyUI", None))
return git_clone_files return git_clone_files
@ -214,7 +176,7 @@ def get_py_urls_from_json(json_file):
if node.get('install_type') == 'copy': if node.get('install_type') == 'copy':
files = node.get('files', []) files = node.get('files', [])
if files: if files:
py_files.append((files[0], node.get('title'), node.get('preemptions'), node.get('nodename_pattern'))) py_files.append((files[0], node.get('title'), node.get('nodename_pattern')))
return py_files return py_files
@ -227,7 +189,7 @@ def clone_or_pull_git_repository(git_url):
try: try:
repo = Repo(repo_dir) repo = Repo(repo_dir)
origin = repo.remote(name="origin") origin = repo.remote(name="origin")
origin.pull() origin.pull(rebase=True)
repo.git.submodule('update', '--init', '--recursive') repo.git.submodule('update', '--init', '--recursive')
print(f"Pulling {repo_name}...") print(f"Pulling {repo_name}...")
except Exception as e: except Exception as e:
@ -246,125 +208,27 @@ def update_custom_nodes():
node_info = {} node_info = {}
git_url_titles_preemptions = get_git_urls_from_json('custom-node-list.json') git_url_titles = get_git_urls_from_json('custom-node-list.json')
def process_git_url_title(url, title, preemptions, node_pattern): def process_git_url_title(url, title, node_pattern):
name = os.path.basename(url) name = os.path.basename(url)
if name.endswith(".git"): if name.endswith(".git"):
name = name[:-4] name = name[:-4]
node_info[name] = (url, title, preemptions, node_pattern) node_info[name] = (url, title, node_pattern)
if not skip_update: clone_or_pull_git_repository(url)
clone_or_pull_git_repository(url)
def process_git_stats(git_url_titles_preemptions): with concurrent.futures.ThreadPoolExecutor(10) as executor:
GITHUB_STATS_CACHE_FILENAME = 'github-stats-cache.json' for url, title, node_pattern in git_url_titles:
GITHUB_STATS_FILENAME = 'github-stats.json' executor.submit(process_git_url_title, url, title, node_pattern)
github_stats = {}
try:
with open(GITHUB_STATS_CACHE_FILENAME, 'r', encoding='utf-8') as file:
github_stats = json.load(file)
except FileNotFoundError:
pass
def is_rate_limit_exceeded():
return g.rate_limiting[0] == 0
if is_rate_limit_exceeded():
print(f"GitHub API Rate Limit Exceeded: remained - {(g.rate_limiting_resettime - datetime.datetime.now().timestamp())/60:.2f} min")
else:
def renew_stat(url):
if is_rate_limit_exceeded():
return
if 'github.com' not in url:
return None
print('.', end="")
sys.stdout.flush()
try:
# Parsing the URL
parsed_url = urlparse(url)
domain = parsed_url.netloc
path = parsed_url.path
path_parts = path.strip("/").split("/")
if len(path_parts) >= 2 and domain == "github.com":
owner_repo = "/".join(path_parts[-2:])
repo = g.get_repo(owner_repo)
last_update = repo.pushed_at.strftime("%Y-%m-%d %H:%M:%S") if repo.pushed_at else 'N/A'
item = {
"stars": repo.stargazers_count,
"last_update": last_update,
"cached_time": datetime.datetime.now().timestamp(),
}
return url, item
else:
print(f"\nInvalid URL format for GitHub repository: {url}\n")
except Exception as e:
print(f"\nERROR on {url}\n{e}")
return None
# resolve unresolved urls
with concurrent.futures.ThreadPoolExecutor(11) as executor:
futures = []
for url, title, preemptions, node_pattern in git_url_titles_preemptions:
if url not in github_stats:
futures.append(executor.submit(renew_stat, url))
for future in concurrent.futures.as_completed(futures):
url_item = future.result()
if url_item is not None:
url, item = url_item
github_stats[url] = item
# renew outdated cache
outdated_urls = []
for k, v in github_stats.items():
elapsed = (datetime.datetime.now().timestamp() - v['cached_time'])
if elapsed > 60*60*12: # 12 hours
outdated_urls.append(k)
with concurrent.futures.ThreadPoolExecutor(11) as executor:
for url in outdated_urls:
futures.append(executor.submit(renew_stat, url))
for future in concurrent.futures.as_completed(futures):
url_item = future.result()
if url_item is not None:
url, item = url_item
github_stats[url] = item
with open('github-stats-cache.json', 'w', encoding='utf-8') as file:
json.dump(github_stats, file, ensure_ascii=False, indent=4)
with open(GITHUB_STATS_FILENAME, 'w', encoding='utf-8') as file:
for v in github_stats.values():
if "cached_time" in v:
del v["cached_time"]
github_stats = dict(sorted(github_stats.items()))
json.dump(github_stats, file, ensure_ascii=False, indent=4)
print(f"Successfully written to {GITHUB_STATS_FILENAME}.")
if not skip_stat_update:
process_git_stats(git_url_titles_preemptions)
with concurrent.futures.ThreadPoolExecutor(11) as executor:
for url, title, preemptions, node_pattern in git_url_titles_preemptions:
executor.submit(process_git_url_title, url, title, preemptions, node_pattern)
py_url_titles_and_pattern = get_py_urls_from_json('custom-node-list.json') py_url_titles_and_pattern = get_py_urls_from_json('custom-node-list.json')
def download_and_store_info(url_title_preemptions_and_pattern): def download_and_store_info(url_title_and_pattern):
url, title, preemptions, node_pattern = url_title_preemptions_and_pattern url, title, node_pattern = url_title_and_pattern
name = os.path.basename(url) name = os.path.basename(url)
if name.endswith(".py"): if name.endswith(".py"):
node_info[name] = (url, title, preemptions, node_pattern) node_info[name] = (url, title, node_pattern)
try: try:
download_url(url, temp_dir) download_url(url, temp_dir)
@ -398,24 +262,15 @@ def gen_json(node_info):
dirname = os.path.basename(dirname) dirname = os.path.basename(dirname)
if 'Jovimetrix' in dirname: if len(nodes) > 0 or (dirname in node_info and node_info[dirname][2] is not None):
pass
if len(nodes) > 0 or (dirname in node_info and node_info[dirname][3] is not None):
nodes = list(nodes) nodes = list(nodes)
nodes.sort() nodes.sort()
if dirname in node_info: if dirname in node_info:
git_url, title, preemptions, node_pattern = node_info[dirname] git_url, title, node_pattern = node_info[dirname]
metadata['title_aux'] = title metadata['title_aux'] = title
if preemptions is not None:
metadata['preemptions'] = preemptions
if node_pattern is not None: if node_pattern is not None:
metadata['nodename_pattern'] = node_pattern metadata['nodename_pattern'] = node_pattern
data[git_url] = (nodes, metadata) data[git_url] = (nodes, metadata)
else: else:
print(f"WARN: {dirname} is removed from custom-node-list.json") print(f"WARN: {dirname} is removed from custom-node-list.json")
@ -423,22 +278,17 @@ def gen_json(node_info):
for file in node_files: for file in node_files:
nodes, metadata = scan_in_file(file) nodes, metadata = scan_in_file(file)
if len(nodes) > 0 or (dirname in node_info and node_info[dirname][3] is not None): if len(nodes) > 0 or (dirname in node_info and node_info[dirname][2] is not None):
nodes = list(nodes) nodes = list(nodes)
nodes.sort() nodes.sort()
file = os.path.basename(file) file = os.path.basename(file)
if file in node_info: if file in node_info:
url, title, preemptions, node_pattern = node_info[file] url, title, node_pattern = node_info[file]
metadata['title_aux'] = title metadata['title_aux'] = title
if preemptions is not None:
metadata['preemptions'] = preemptions
if node_pattern is not None: if node_pattern is not None:
metadata['nodename_pattern'] = node_pattern metadata['nodename_pattern'] = node_pattern
data[url] = (nodes, metadata) data[url] = (nodes, metadata)
else: else:
print(f"Missing info: {file}") print(f"Missing info: {file}")
@ -449,7 +299,7 @@ def gen_json(node_info):
for extension in extensions: for extension in extensions:
node_list_json_path = os.path.join(temp_dir, extension, 'node_list.json') node_list_json_path = os.path.join(temp_dir, extension, 'node_list.json')
if os.path.exists(node_list_json_path): if os.path.exists(node_list_json_path):
git_url, title, preemptions, node_pattern = node_info[extension] git_url, title, node_pattern = node_info[extension]
with open(node_list_json_path, 'r', encoding='utf-8') as f: with open(node_list_json_path, 'r', encoding='utf-8') as f:
node_list_json = json.load(f) node_list_json = json.load(f)
@ -465,13 +315,8 @@ def gen_json(node_info):
nodes.add(x.strip()) nodes.add(x.strip())
metadata_in_url['title_aux'] = title metadata_in_url['title_aux'] = title
if preemptions is not None:
metadata['preemptions'] = preemptions
if node_pattern is not None: if node_pattern is not None:
metadata_in_url['nodename_pattern'] = node_pattern metadata_in_url['nodename_pattern'] = node_pattern
nodes = list(nodes) nodes = list(nodes)
nodes.sort() nodes.sort()
data[git_url] = (nodes, metadata_in_url) data[git_url] = (nodes, metadata_in_url)
@ -489,4 +334,3 @@ updated_node_info = update_custom_nodes()
print("\n# 'extension-node-map.json' file is generated.\n") print("\n# 'extension-node-map.json' file is generated.\n")
gen_json(updated_node_info) gen_json(updated_node_info)
print("\nDONE.\n")

2
scripts/install-comfyui-venv-linux.sh

@ -4,9 +4,9 @@ git clone https://github.com/ltdrdata/ComfyUI-Manager
cd .. cd ..
python -m venv venv python -m venv venv
source venv/bin/activate source venv/bin/activate
python -m pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu121
python -m pip install -r requirements.txt python -m pip install -r requirements.txt
python -m pip install -r custom_nodes/ComfyUI-Manager/requirements.txt python -m pip install -r custom_nodes/ComfyUI-Manager/requirements.txt
python -m pip install torchvision
cd .. cd ..
echo "#!/bin/bash" > run_gpu.sh echo "#!/bin/bash" > run_gpu.sh
echo "cd ComfyUI" >> run_gpu.sh echo "cd ComfyUI" >> run_gpu.sh

17
scripts/install-comfyui-venv-win.bat

@ -4,14 +4,17 @@ git clone https://github.com/ltdrdata/ComfyUI-Manager
cd .. cd ..
python -m venv venv python -m venv venv
call venv/Scripts/activate call venv/Scripts/activate
python -m pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu121
python -m pip install -r requirements.txt python -m pip install -r requirements.txt
python -m pip install -r custom_nodes/ComfyUI-Manager/requirements.txt python -m pip install -r custom_nodes/ComfyUI-Manager/requirements.txt
python -m pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu118 xformers
cd .. cd ..
echo "cd ComfyUI" >> run_gpu.bat echo "cd ComfyUI" >> run_gpu.sh
echo "call venv/Scripts/activate" >> run_gpu.bat echo "call venv/Scripts/activate" >> run_gpu.sh
echo "python main.py" >> run_gpu.bat echo "python main.py" >> run_gpu.sh
chmod +x run_gpu.sh
echo "cd ComfyUI" >> run_cpu.bat echo "#!/bin/bash" > run_cpu.sh
echo "call venv/Scripts/activate" >> run_cpu.bat echo "cd ComfyUI" >> run_cpu.sh
echo "python main.py --cpu" >> run_cpu.bat echo "call venv/Scripts/activate" >> run_cpu.sh
echo "python main.py --cpu" >> run_cpu.sh
chmod +x run_cpu.sh

Loading…
Cancel
Save