Compare commits
17 Commits
tests/api-
...
3.32.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0048754fe8 | ||
|
|
5c0bd0f79c | ||
|
|
669cdffe08 | ||
|
|
3cd553301b | ||
|
|
db7ef4f253 | ||
|
|
a09704567c | ||
|
|
21fe577a2e | ||
|
|
9f258f5c9c | ||
|
|
9cd088feb0 | ||
|
|
89e3828138 | ||
|
|
731c89dc27 | ||
|
|
3d920cab4d | ||
|
|
470b8c1fb8 | ||
|
|
dbf988fd5a | ||
|
|
0031743ad4 | ||
|
|
0f2c0ab65d | ||
|
|
53244b794f |
@@ -1356,10 +1356,10 @@
|
|||||||
{
|
{
|
||||||
"author": "ArtVentureX",
|
"author": "ArtVentureX",
|
||||||
"title": "AnimateDiff",
|
"title": "AnimateDiff",
|
||||||
"reference": "https://github.com/ArtVentureX/comfyui-animatediff",
|
"reference": "https://github.com/SipherAGI/comfyui-animatediff",
|
||||||
"pip": ["flash_attn"],
|
"pip": ["flash_attn"],
|
||||||
"files": [
|
"files": [
|
||||||
"https://github.com/ArtVentureX/comfyui-animatediff"
|
"https://github.com/SipherAGI/comfyui-animatediff"
|
||||||
],
|
],
|
||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "AnimateDiff integration for ComfyUI, adapts from sd-webui-animatediff.\n[w/You only need to download one of [a/mm_sd_v14.ckpt](https://huggingface.co/guoyww/animatediff/resolve/main/mm_sd_v14.ckpt) | [a/mm_sd_v15.ckpt](https://huggingface.co/guoyww/animatediff/resolve/main/mm_sd_v15.ckpt). Put the model weights under %%ComfyUI/custom_nodes/comfyui-animatediff/models%%. DO NOT change model filename.]"
|
"description": "AnimateDiff integration for ComfyUI, adapts from sd-webui-animatediff.\n[w/You only need to download one of [a/mm_sd_v14.ckpt](https://huggingface.co/guoyww/animatediff/resolve/main/mm_sd_v14.ckpt) | [a/mm_sd_v15.ckpt](https://huggingface.co/guoyww/animatediff/resolve/main/mm_sd_v15.ckpt). Put the model weights under %%ComfyUI/custom_nodes/comfyui-animatediff/models%%. DO NOT change model filename.]"
|
||||||
@@ -1905,7 +1905,7 @@
|
|||||||
{
|
{
|
||||||
"author": "Extraltodeus",
|
"author": "Extraltodeus",
|
||||||
"title": "pre_cfg_comfy_nodes_for_ComfyUI",
|
"title": "pre_cfg_comfy_nodes_for_ComfyUI",
|
||||||
"id": "precfg",
|
"id": "pre_cfg_comfy_nodes_for_comfyui",
|
||||||
"reference": "https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI",
|
"reference": "https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI",
|
||||||
"files": [
|
"files": [
|
||||||
"https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI"
|
"https://github.com/Extraltodeus/pre_cfg_comfy_nodes_for_ComfyUI"
|
||||||
@@ -3912,13 +3912,13 @@
|
|||||||
{
|
{
|
||||||
"author": "fexli",
|
"author": "fexli",
|
||||||
"title": "fexli-util-node-comfyui",
|
"title": "fexli-util-node-comfyui",
|
||||||
"id": "fexli",
|
"id": "fexli-util-node-comfyui",
|
||||||
"reference": "https://github.com/fexli/fexli-util-node-comfyui",
|
"reference": "https://github.com/fexli/fexli-util-node-comfyui",
|
||||||
"files": [
|
"files": [
|
||||||
"https://github.com/fexli/fexli-util-node-comfyui"
|
"https://github.com/fexli/fexli-util-node-comfyui"
|
||||||
],
|
],
|
||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Nodes:FEImagePadForOutpaint, FEColorOut, FEColor2Image, FERandomizedColor2Image"
|
"description": "A set of Fe's Util nodes for ComfyUI"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "AbyssBadger0",
|
"author": "AbyssBadger0",
|
||||||
@@ -7780,6 +7780,16 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "An extension that's adds advanced audio processing capabilities to ComfyUI with professional-grade audio effects and AI-powered audio enhancement."
|
"description": "An extension that's adds advanced audio processing capabilities to ComfyUI with professional-grade audio effects and AI-powered audio enhancement."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"author": "ShmuelRonen",
|
||||||
|
"title": "ComfyUI-Gemini_TTS",
|
||||||
|
"reference": "https://github.com/ShmuelRonen/ComfyUI-Gemini_TTS",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/ShmuelRonen/ComfyUI-Gemini_TTS"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A powerful ComfyUI custom node that brings Google's Gemini TTS capabilities directly to your workflow. Generate high-quality speech with 30+ voices supporting both free and paid tiers."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "redhottensors",
|
"author": "redhottensors",
|
||||||
"title": "ComfyUI-Prediction",
|
"title": "ComfyUI-Prediction",
|
||||||
@@ -7946,6 +7956,16 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "A ComfyUI implementation of Latent Bridge Matching (LBM) for efficient image relighting. This node utilizes the LBM algorithm to perform single-step image-to-image translation specifically for relighting tasks."
|
"description": "A ComfyUI implementation of Latent Bridge Matching (LBM) for efficient image relighting. This node utilizes the LBM algorithm to perform single-step image-to-image translation specifically for relighting tasks."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"author": "1038lab",
|
||||||
|
"title": "ComfyUI-JoyCaption",
|
||||||
|
"reference": "https://github.com/1038lab/ComfyUI-JoyCaption",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/1038lab/ComfyUI-JoyCaption"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "ComfyUI custom node powered by LLaVA VLM for advanced image captioning with customizable styles and memory-efficient inference."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "Klinter",
|
"author": "Klinter",
|
||||||
"title": "Klinter_nodes",
|
"title": "Klinter_nodes",
|
||||||
@@ -9368,17 +9388,6 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Unofficial implementation of [a/LatentSync](https://github.com/bytedance/LatentSync) for ComfyUI"
|
"description": "Unofficial implementation of [a/LatentSync](https://github.com/bytedance/LatentSync) for ComfyUI"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"author": "shinich39",
|
|
||||||
"title": "comfyui-random-node",
|
|
||||||
"id": "random-node",
|
|
||||||
"reference": "https://github.com/shinich39/comfyui-ramdom-node",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/shinich39/comfyui-ramdom-node"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Shuffle nodes after queue added. [w/Repository name has been changed from comfyui-random-node-39 to comfyui-random-node. Please remove and reinstall it.]"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"author": "shinich39",
|
"author": "shinich39",
|
||||||
"title": "comfyui-get-meta",
|
"title": "comfyui-get-meta",
|
||||||
@@ -9439,6 +9448,16 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Fix node to top."
|
"description": "Fix node to top."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"author": "shinich39",
|
||||||
|
"title": "comfyui-break-workflow",
|
||||||
|
"reference": "https://github.com/shinich39/comfyui-break-workflow",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/shinich39/comfyui-break-workflow"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Break the execution, save the incompleted image then continue later."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "wei30172",
|
"author": "wei30172",
|
||||||
"title": "comfygen",
|
"title": "comfygen",
|
||||||
@@ -10823,6 +10842,16 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Use DICE-Talk in ComfyUI,which is a method about Correlation-Aware Emotional Talking Portrait Generation."
|
"description": "Use DICE-Talk in ComfyUI,which is a method about Correlation-Aware Emotional Talking Portrait Generation."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"author": "smthemex",
|
||||||
|
"title": "ComfyUI_VisualCloze",
|
||||||
|
"reference": "https://github.com/smthemex/ComfyUI_VisualCloze",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/smthemex/ComfyUI_VisualCloze"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "VisualCloze: A Universal Image Generation Framework via Visual In-Context Learning,you can use it in ComfyUI"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "choey",
|
"author": "choey",
|
||||||
"title": "Comfy-Topaz",
|
"title": "Comfy-Topaz",
|
||||||
@@ -13499,6 +13528,17 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Create immersive 3D stereoscopic images and videos! Transform your ComfyUI generations into stunning side-by-side 3D visuals for videos and image sequences. Powered by Depth-Anything-V2, no external depth maps needed. Perfect for VR, 3D displays, and cross-eyed viewing - no special glasses required!"
|
"description": "Create immersive 3D stereoscopic images and videos! Transform your ComfyUI generations into stunning side-by-side 3D visuals for videos and image sequences. Powered by Depth-Anything-V2, no external depth maps needed. Perfect for VR, 3D displays, and cross-eyed viewing - no special glasses required!"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"author": "MrSamSeen",
|
||||||
|
"title": "ComfyUI_SSBeforeAfterNode",
|
||||||
|
"id": "ComfyUI_SSBeforeAfterNode",
|
||||||
|
"reference": "https://github.com/MrSamSeen/ComfyUI_SSBeforeAfterNode",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/MrSamSeen/ComfyUI_SSBeforeAfterNode"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Two powerful custom nodes for ComfyUI to create stunning before-and-after transition videos. These nodes are designed for visual comparisons, transformations, and creative effects, supporting both standard and depth map-based transitions."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "jroc22",
|
"author": "jroc22",
|
||||||
"title": "ComfyUI-CSV-prompt-builder",
|
"title": "ComfyUI-CSV-prompt-builder",
|
||||||
@@ -14029,6 +14069,16 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Remove content inside 'think' tag from reasoning llm"
|
"description": "Remove content inside 'think' tag from reasoning llm"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"author": "lrzjason",
|
||||||
|
"title": "ComfyUI Watermark Detection Node",
|
||||||
|
"reference": "https://github.com/lrzjason/ComfyUI-Watermark-Detection",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/lrzjason/ComfyUI-Watermark-Detection"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "This custom node for ComfyUI provides watermark detection capabilities using a YOLO model trained by [a/fancyfeast](https://huggingface.co/fancyfeast), the creator of JoyCaption. The model is originally hosted at [a/Hugging Face Space](https://huggingface.co/spaces/fancyfeast/joycaption-watermark-detection)."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "cozy_comm",
|
"author": "cozy_comm",
|
||||||
"title": "Cozy Communication",
|
"title": "Cozy Communication",
|
||||||
@@ -15222,7 +15272,6 @@
|
|||||||
"https://github.com/Hellrunner2k/ComfyUI-HellrunnersMagicalNodes"
|
"https://github.com/Hellrunner2k/ComfyUI-HellrunnersMagicalNodes"
|
||||||
],
|
],
|
||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
|
|
||||||
"description": "Magical nodes that are meant for integration and science of course. ^^ Foundational Helpers and smart Containers that use automated functionalities to make room for creative use. A magical pack-synergy is at hand that does not require much extra clutter to make advanced techniques pop beautifully. The idea was to create universal artist's precision tools that do not care what you throw at them."
|
"description": "Magical nodes that are meant for integration and science of course. ^^ Foundational Helpers and smart Containers that use automated functionalities to make room for creative use. A magical pack-synergy is at hand that does not require much extra clutter to make advanced techniques pop beautifully. The idea was to create universal artist's precision tools that do not care what you throw at them."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -15521,7 +15570,7 @@
|
|||||||
"https://github.com/gseth/ControlAltAI-Nodes"
|
"https://github.com/gseth/ControlAltAI-Nodes"
|
||||||
],
|
],
|
||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Quality of Life ComfyUI nodes starting with Flux Resolution Calculator and Flux Sampler."
|
"description": "Quality of Life Nodes from ControlAltAI. Flux Resolution Calculator, Flux Sampler, Flux Union ControlNet Apply, Noise Plus Blend, Boolean Logic, and Flux Region Nodes."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "OliverCrosby",
|
"author": "OliverCrosby",
|
||||||
@@ -16804,9 +16853,9 @@
|
|||||||
{
|
{
|
||||||
"author": "silveroxides",
|
"author": "silveroxides",
|
||||||
"title": "Model and Checkpoint Loaders for NF4 and FP4",
|
"title": "Model and Checkpoint Loaders for NF4 and FP4",
|
||||||
"reference": "https://github.com/silveroxides/ComfyUI_bitsandbytes_NF4",
|
"reference": "https://github.com/silveroxides/ComfyUI_bnb_nf4_fp4_Loaders",
|
||||||
"files": [
|
"files": [
|
||||||
"https://github.com/silveroxides/ComfyUI_bitsandbytes_NF4"
|
"https://github.com/silveroxides/ComfyUI_bnb_nf4_fp4_Loaders"
|
||||||
],
|
],
|
||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Nodes for loading both Checkpoints and UNET/Diffussion models quantized to bitsandbytes NF4 or FP4 format.\nStill under development and some limitations such as using LoRA might apply still."
|
"description": "Nodes for loading both Checkpoints and UNET/Diffussion models quantized to bitsandbytes NF4 or FP4 format.\nStill under development and some limitations such as using LoRA might apply still."
|
||||||
@@ -16842,6 +16891,16 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Scheduler for ComfyUI and an attempt at optimized scheduler for the Chroma architecture."
|
"description": "Scheduler for ComfyUI and an attempt at optimized scheduler for the Chroma architecture."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"author": "silveroxides",
|
||||||
|
"title": "ComfyUI_EmbeddingToolkit",
|
||||||
|
"reference": "https://github.com/silveroxides/ComfyUI_EmbeddingToolkit",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/silveroxides/ComfyUI_EmbeddingToolkit"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Toolkit for creating embeddings for various models in ComfyUI."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "turkyden",
|
"author": "turkyden",
|
||||||
"title": "ComfyUI-SmartCrop",
|
"title": "ComfyUI-SmartCrop",
|
||||||
@@ -18277,13 +18336,23 @@
|
|||||||
{
|
{
|
||||||
"author": "LevelPixel",
|
"author": "LevelPixel",
|
||||||
"title": "ComfyUI_LevelPixel",
|
"title": "ComfyUI_LevelPixel",
|
||||||
"id": "levelpixel",
|
|
||||||
"reference": "https://github.com/LevelPixel/ComfyUI-LevelPixel",
|
"reference": "https://github.com/LevelPixel/ComfyUI-LevelPixel",
|
||||||
"files": [
|
"files": [
|
||||||
"https://github.com/LevelPixel/ComfyUI-LevelPixel"
|
"https://github.com/LevelPixel/ComfyUI-LevelPixel"
|
||||||
],
|
],
|
||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Various nodes of the Level Pixel company. Includes convenient advanced nodes for working with images from folders; counting files in a folder; cleaning memory; tag filters. Model Unloader, LLM Unloader (GGUF unloaders), Free memory, Tag Filters, Tag Category Filters, Tag Choice Parser, File counter, Image Loader From Path (with counters), Image Remove Background based on RemBG, Autotagger."
|
"description": "Main nodes of the Level Pixel company. Includes convenient nodes for working with images from folders; counting files in a folder; cleaning memory; tag filters. Model Unloader, LLM Unloader, Free memory, Tag Filters, Tag Category Filters, Tag Choice Parser, File counter, Image Loader From Path (with counters), Image Remove Background based on RemBG, Autotagger."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "LevelPixel",
|
||||||
|
"title": "ComfyUI_LevelPixel_Advanced",
|
||||||
|
"id": "levelpixel_advanced",
|
||||||
|
"reference": "https://github.com/LevelPixel/ComfyUI-LevelPixel-Advanced",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/LevelPixel/ComfyUI-LevelPixel-Advanced"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Advanced nodes of the Level Pixel company. Includes convenient advanced nodes for working with LLM и VLM models (LLaVa) with GGUF format. Qwen2.5-VL and Qwen2.5 supported. Also included is a node for the RAM model. Nodes have the ability to automatically unload models from VRAM."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "morino-kumasan",
|
"author": "morino-kumasan",
|
||||||
@@ -19408,6 +19477,26 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "ComfyUI-MoviiGen is now available in ComfyUI, MoviiGen 1.1 is a cutting-edge video generation model that excels in cinematic aesthetics and visual quality."
|
"description": "ComfyUI-MoviiGen is now available in ComfyUI, MoviiGen 1.1 is a cutting-edge video generation model that excels in cinematic aesthetics and visual quality."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"author": "Yuan-ManX",
|
||||||
|
"title": "ComfyUI-AniSora",
|
||||||
|
"reference": "https://github.com/Yuan-ManX/ComfyUI-AniSora",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/Yuan-ManX/ComfyUI-AniSora"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "ComfyUI-AniSora is now available in ComfyUI, Index-AniSora is the most powerful open-source animated video generation model. It enables one-click creation of video shots across diverse anime styles including series episodes, Chinese original animations, manga adaptations, VTuber content, anime PVs, mad-style parodies(鬼畜动画), and more!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Yuan-ManX",
|
||||||
|
"title": "ComfyUI-Bagel",
|
||||||
|
"reference": "https://github.com/Yuan-ManX/ComfyUI-Bagel",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/Yuan-ManX/ComfyUI-Bagel"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "ComfyUI-Bagel is now available in ComfyUI, BAGEL is an open‑source multimodal foundation model with 7B active parameters (14B total) trained on large‑scale interleaved multimodal data."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "Starnodes2024",
|
"author": "Starnodes2024",
|
||||||
"title": "ComfyUI_StarNodes",
|
"title": "ComfyUI_StarNodes",
|
||||||
@@ -20111,6 +20200,26 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "A visually stunning extension for ComfyUI that adds beautiful, customizable animations to both links and nodes in your workflow, with a focus on performance and customization. Includes an end-of-render animation and a text visibility tool for nodes. No extra packages are required, works with the latest version of ComfyUI, and should be compatible with most workflows. Larger workflows may experience performance issues, especially if you have a lot of nodes and are using a lower end system."
|
"description": "A visually stunning extension for ComfyUI that adds beautiful, customizable animations to both links and nodes in your workflow, with a focus on performance and customization. Includes an end-of-render animation and a text visibility tool for nodes. No extra packages are required, works with the latest version of ComfyUI, and should be compatible with most workflows. Larger workflows may experience performance issues, especially if you have a lot of nodes and are using a lower end system."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"author": "AEmotionStudio",
|
||||||
|
"title": "ComfyUI-MagnifyGlass",
|
||||||
|
"reference": "https://github.com/AEmotionStudio/ComfyUI-MagnifyGlass",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/AEmotionStudio/ComfyUI-MagnifyGlass"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "ComfyUI-MagnifyGlass: A powerful & customizable magnifying glass for ComfyUI. Zoom into canvas details with smooth controls, configurable activation, custom styles (shape, size, border) & WebGL performance."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "AEmotionStudio",
|
||||||
|
"title": "ComfyUI-ShaderNoiseKSampler",
|
||||||
|
"reference": "https://github.com/AEmotionStudio/ComfyUI-ShaderNoiseKSampler",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/AEmotionStudio/ComfyUI-ShaderNoiseKSampler"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "ComfyUI-ShaderNoiseKSampler is an advanced custom KSampler node that replaces standard noise generation with a multi-stage shader-based system. Unlike traditional sampling that teleports randomly between different seeds, this tool provides a structured vehicle for exploring the neighborhood around a chosen seed, using mathematical patterns to navigate along coherent paths through latent space."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "xfgexo",
|
"author": "xfgexo",
|
||||||
"title": "EXO Custom ComfyUI Nodes",
|
"title": "EXO Custom ComfyUI Nodes",
|
||||||
@@ -20264,16 +20373,6 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Use an online large language model to describe images."
|
"description": "Use an online large language model to describe images."
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"author": "solution9th",
|
|
||||||
"title": "Comfyui_mobilesam",
|
|
||||||
"reference": "https://github.com/solution9th/Comfyui_mobilesam",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/solution9th/Comfyui_mobilesam"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "NODES: Mobile SAM Model Loader, Mobile SAM Detector, Mobile SAM Predictor"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"author": "ronsantash",
|
"author": "ronsantash",
|
||||||
"title": "ComfyUIFlexiLoRALoader",
|
"title": "ComfyUIFlexiLoRALoader",
|
||||||
@@ -20743,16 +20842,6 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "OuteTTS - Unified Text-To-Speech. A node for ComfyUI"
|
"description": "OuteTTS - Unified Text-To-Speech. A node for ComfyUI"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"author": "mw",
|
|
||||||
"title": "MW-ComfyUI_OuteTTS",
|
|
||||||
"reference": "https://github.com/billwuhao/ComfyUI_OuteTTS",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/billwuhao/ComfyUI_OuteTTS"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "OuteTTS - Unified Text-To-Speech. A node for ComfyUI"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"author": "mw",
|
"author": "mw",
|
||||||
"title": "ComfyUI_IndexTTS",
|
"title": "ComfyUI_IndexTTS",
|
||||||
@@ -20783,6 +20872,16 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "parakeet-tdt-0.6b-v2: Automatic speech recognition (ASR) model designed for high-quality English transcription, featuring support for punctuation, capitalization, and accurate timestamp prediction."
|
"description": "parakeet-tdt-0.6b-v2: Automatic speech recognition (ASR) model designed for high-quality English transcription, featuring support for punctuation, capitalization, and accurate timestamp prediction."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"author": "mw",
|
||||||
|
"title": "Comfyui_HeyGem",
|
||||||
|
"reference": "https://github.com/billwuhao/Comfyui_HeyGem",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/billwuhao/Comfyui_HeyGem"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "HeyGem AI avatar."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "umiyuki",
|
"author": "umiyuki",
|
||||||
"title": "ComfyUI Pad To Eight",
|
"title": "ComfyUI Pad To Eight",
|
||||||
@@ -21381,6 +21480,16 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "ComfyUI zip package image processing"
|
"description": "ComfyUI zip package image processing"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"author": "hmwl",
|
||||||
|
"title": "ComfyUI-TaskMonitor",
|
||||||
|
"reference": "https://github.com/hmwl/ComfyUI-TaskMonitor",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/hmwl/ComfyUI-TaskMonitor"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A powerful task monitoring extension for ComfyUI that provides real-time progress tracking, workflow statistics, and execution monitoring."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "nisimjoseph",
|
"author": "nisimjoseph",
|
||||||
"title": "ComfyUI OpenAI Prompter",
|
"title": "ComfyUI OpenAI Prompter",
|
||||||
@@ -22809,6 +22918,16 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "ComfyUI node that adds Brightness, RGB channels, and Depth of Field to AI-generated image"
|
"description": "ComfyUI node that adds Brightness, RGB channels, and Depth of Field to AI-generated image"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"author": "KAVVATARE",
|
||||||
|
"title": "RightEyeDisparity",
|
||||||
|
"reference": "https://github.com/KAVVATARE/ComfyUI_RightEyeDisparity",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/KAVVATARE/ComfyUI_RightEyeDisparity"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A simple ComfyUI node for generating right eye disparity for VR videos"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "fat-tire",
|
"author": "fat-tire",
|
||||||
"title": "ComfyUI Unified Media Suite",
|
"title": "ComfyUI Unified Media Suite",
|
||||||
@@ -23388,6 +23507,26 @@
|
|||||||
"description": "I took the original source code from the repository [a/ComfyUI_ACE-Step](https://github.com/billwuhao/ComfyUI_ACE-Step) and modified it to make the model loading explicit instead of hidden.",
|
"description": "I took the original source code from the repository [a/ComfyUI_ACE-Step](https://github.com/billwuhao/ComfyUI_ACE-Step) and modified it to make the model loading explicit instead of hidden.",
|
||||||
"install_type": "git-clone"
|
"install_type": "git-clone"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"author": "thezveroboy",
|
||||||
|
"title": "ComfyUI Random Image Loader",
|
||||||
|
"reference": "https://github.com/thezveroboy/comfyui-random-image-loader",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/thezveroboy/comfyui-random-image-loader"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A custom node for ComfyUI that loads a random image from a specified folder and outputs it in the standard ComfyUI IMAGE format, along with a MASK and the image path as STRING. Images are loaded in their original dimensions."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "thezveroboy",
|
||||||
|
"title": "ComfyUI-LUT",
|
||||||
|
"reference": "https://github.com/thezveroboy/ComfyUI-lut",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/thezveroboy/ComfyUI-lut"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Custom nodes for ComfyUI for simple LUT file extraction from any image."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "tatookan",
|
"author": "tatookan",
|
||||||
"title": "comfyui_ssl_gemini_EXP",
|
"title": "comfyui_ssl_gemini_EXP",
|
||||||
@@ -23953,16 +24092,6 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Call LLM and VLM in a simple way using the OpenAI API standard from ComfyUI"
|
"description": "Call LLM and VLM in a simple way using the OpenAI API standard from ComfyUI"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"author": "thezveroboy",
|
|
||||||
"title": "ComfyUI Random Image Loader",
|
|
||||||
"reference": "https://github.com/thezveroboy/comfyui-random-image-loader",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/thezveroboy/comfyui-random-image-loader"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "A custom node for ComfyUI that loads a random image from a specified folder and outputs it in the standard ComfyUI IMAGE format, along with a MASK and the image path as STRING. Images are loaded in their original dimensions."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"author": "rookiepsi",
|
"author": "rookiepsi",
|
||||||
"title": "ComfyUI Extended",
|
"title": "ComfyUI Extended",
|
||||||
@@ -24594,7 +24723,7 @@
|
|||||||
"https://github.com/WarpedAnimation/ComfyUI-WarpedToolset"
|
"https://github.com/WarpedAnimation/ComfyUI-WarpedToolset"
|
||||||
],
|
],
|
||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Custom tool set mostly for Hunyuan Video, but includes some WAN Video nodes."
|
"description": "A toolset for Hunyuan Video (mainly), with some additional nodes applicable to Framepack Video and WAN Video"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "Jint8888",
|
"author": "Jint8888",
|
||||||
@@ -25487,6 +25616,16 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "quick Comfy Node to convert input waveform audio to MP3"
|
"description": "quick Comfy Node to convert input waveform audio to MP3"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"author": "SanDiegoDude",
|
||||||
|
"title": "ComfyUI-DeepStereo",
|
||||||
|
"reference": "https://github.com/SanDiegoDude/ComfyUI-DeepStereo",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/SanDiegoDude/ComfyUI-DeepStereo"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "ComfyUI nodes for DeepStereo, an auto-autostereogram generator"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "tavyra",
|
"author": "tavyra",
|
||||||
"title": "ComfyUI_Curves",
|
"title": "ComfyUI_Curves",
|
||||||
@@ -25595,7 +25734,7 @@
|
|||||||
"https://github.com/newtextdoc1111/ComfyUI-Autocomplete-Plus"
|
"https://github.com/newtextdoc1111/ComfyUI-Autocomplete-Plus"
|
||||||
],
|
],
|
||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Custom node to add autocomplete functionality [ComfyUI-Autocomplete-Plus](https://github.com/newtextdoc1111/ComfyUI-Autocomplete-Plus)."
|
"description": "Autocomplete and Related Tag display for ComfyUI"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "otacoo",
|
"author": "otacoo",
|
||||||
@@ -25673,7 +25812,7 @@
|
|||||||
"author": "TrophiHunter",
|
"author": "TrophiHunter",
|
||||||
"title": "Photography Nodes",
|
"title": "Photography Nodes",
|
||||||
"id": "comfyui-photography-nodes",
|
"id": "comfyui-photography-nodes",
|
||||||
"reference": "https://www.trophihunter.com/software-plugins/comfyui_photography_nodes",
|
"reference": "https://github.com/TrophiHunter/ComfyUI_Photography_Nodes",
|
||||||
"files": [
|
"files": [
|
||||||
"https://github.com/TrophiHunter/ComfyUI_Photography_Nodes"
|
"https://github.com/TrophiHunter/ComfyUI_Photography_Nodes"
|
||||||
],
|
],
|
||||||
@@ -25720,16 +25859,6 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "for use jimeng ai in comfyui"
|
"description": "for use jimeng ai in comfyui"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"author": "AEmotionStudio",
|
|
||||||
"title": "ComfyUI-MagnifyGlass",
|
|
||||||
"reference": "https://github.com/AEmotionStudio/ComfyUI-MagnifyGlass",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/AEmotionStudio/ComfyUI-MagnifyGlass"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "ComfyUI-MagnifyGlass: A powerful & customizable magnifying glass for ComfyUI. Zoom into canvas details with smooth controls, configurable activation, custom styles (shape, size, border) & WebGL performance."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"author": "Kyron Mahan",
|
"author": "Kyron Mahan",
|
||||||
"title": "ComfyUI Smart Scaler",
|
"title": "ComfyUI Smart Scaler",
|
||||||
@@ -25863,6 +25992,219 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "A utility node for extracting and trimming filenames from file paths"
|
"description": "A utility node for extracting and trimming filenames from file paths"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"author": "craig-tanaka",
|
||||||
|
"title": "ComfyUI Anime Segmentation Nodes v1.1.0",
|
||||||
|
"reference": "https://github.com/craig-tanaka/comfyui_animeseg",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/craig-tanaka/comfyui_animeseg"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "This is a set of custom nodes for ComfyUI that provide anime-style image segmentation using efficient pre-trained models."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "lepiai",
|
||||||
|
"title": "ComfyUI-Minitools",
|
||||||
|
"reference": "https://github.com/lepiai/ComfyUI-Minitools",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/lepiai/ComfyUI-Minitools"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "ComfyUI Mini Toolkit – Helps reduce node redundancy. Let’s see if there’s time to keep it updated regularly."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "wildminder",
|
||||||
|
"title": "ComfyUI-KEEP",
|
||||||
|
"reference": "https://github.com/wildminder/ComfyUI-KEEP",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/wildminder/ComfyUI-KEEP"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "ComfyUI-KEEP: Kalman-Inspired Feature Propagation for Video Face Super-Resolution in ComfyUI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "cloudkoala",
|
||||||
|
"title": "comfyui-koala",
|
||||||
|
"reference": "https://github.com/cloudkoala/comfyui-koala",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/cloudkoala/comfyui-koala"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A collection of custom nodes for ComfyUI focused on aspect ratio management and other utilities."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Limbicnation",
|
||||||
|
"title": "ComfyUIDepthEstimation",
|
||||||
|
"reference": "https://github.com/Limbicnation/ComfyUIDepthEstimation",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/Limbicnation/ComfyUIDepthEstimation"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A robust custom depth estimation node for ComfyUI using Depth-Anything models. It integrates depth estimation with configurable post-processing options including blur, median filtering, contrast enhancement, and gamma correction."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Limbicnation",
|
||||||
|
"title": "Depth Estimation Node",
|
||||||
|
"reference": "https://github.com/Limbicnation/ComfyUIDepthEstimation",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/Limbicnation/ComfyUIDepthEstimation"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A robust custom depth estimation node for ComfyUI using Depth-Anything models. It integrates depth estimation with configurable post-processing options including blur, median filtering, contrast enhancement, and gamma correction."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Limbicnation",
|
||||||
|
"title": "Transparency Background Remover",
|
||||||
|
"reference": "https://github.com/Limbicnation/ComfyUI-TransparencyBackgroundRemover",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/Limbicnation/ComfyUI-TransparencyBackgroundRemover"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Automatic background removal and transparency generation for ComfyUI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "kevin314",
|
||||||
|
"title": "ComfyUI-FastVideo",
|
||||||
|
"reference": "https://github.com/kevin314/ComfyUI-FastVideo",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/kevin314/ComfyUI-FastVideo"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A custom node suite for ComfyUI that provides accelerated video generation using [a/FastVideo](https://github.com/hao-ai-labs/FastVideo). See the [a/blog post](https://hao-ai-lab.github.io/blogs/fastvideo/) about FastVideo V1 to learn more."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "TensorKaze",
|
||||||
|
"title": "ComfyUI-TkNodes",
|
||||||
|
"id": "ComfyUI-TkNodes",
|
||||||
|
"reference": "https://github.com/TensorKaze/ComfyUI-TkNodes",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/TensorKaze/ComfyUI-TkNodes"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Custom nodes for ComfyUI with advanced image scaling, latent manipulation, and Flux sampling"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "angree",
|
||||||
|
"title": "ComfyUI-Q_GLB_Material_Modifier",
|
||||||
|
"reference": "https://github.com/angree/ComfyUI-Q_GLB_Material_Modifier",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/angree/ComfyUI-Q_GLB_Material_Modifier"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A ComfyUI custom node for enhancing GLB 3D models generated with Hunyuan 3D 2.0. This module helps solve the common 'plastic look' problem by adding realistic materials and smart emissive elements."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "babe-and-spencer-enterprises",
|
||||||
|
"title": "ComfyUI Upload to BASE Node",
|
||||||
|
"reference": "https://github.com/babe-and-spencer-enterprises/base-comfyui-node",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/babe-and-spencer-enterprises/base-comfyui-node"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A custom ComfyUI node that lets you upload generated images directly to your [a/BASE](https://getbase.app/) account — no manual downloads or re-uploads needed."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "R5-Revo",
|
||||||
|
"title": "Universal LLM Node for ComfyUI",
|
||||||
|
"reference": "https://github.com/R5-Revo/llm-node-comfyui",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/R5-Revo/llm-node-comfyui"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "UniversalLLMNode is a custom node for ComfyUI that provides a unified interface to use multiple major LLM APIs, including OpenAI, Anthropic (Claude), Google Gemini, Groq, and Mistral. It is ideal for tasks such as automatically generating high-quality SDXL prompts for image generation."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "jaimitoes",
|
||||||
|
"title": "ComfyUI_Wan2_1_lora_trainer",
|
||||||
|
"reference": "https://github.com/jaimitoes/ComfyUI_Wan2_1_lora_trainer",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/jaimitoes/ComfyUI_Wan2_1_lora_trainer"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "ComfyUI interface adaptation of the musubi-tunner library to train Wan 2.1 loras."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "karthikg-09",
|
||||||
|
"title": "ComfyUI-Vton-Mask",
|
||||||
|
"reference": "https://github.com/karthikg-09/ComfyUI-Vton-Mask",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/karthikg-09/ComfyUI-Vton-Mask"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A lightweight ComfyUI custom node for generating high-quality masks and pose detection for virtual try-on applications. This node extracts only the essential masking functionality from FitDiT without requiring heavy diffusion models."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "pureexe",
|
||||||
|
"title": "DiffusionLight-ComfyUI",
|
||||||
|
"reference": "https://github.com/pureexe/DiffusionLight-ComfyUI",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/pureexe/DiffusionLight-ComfyUI"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "DiffusionLight (Turbo) implemented in ComfyUI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "ComfyAssets",
|
||||||
|
"title": "ComfyUI Prompt Manager",
|
||||||
|
"reference": "https://github.com/ComfyAssets/ComfyUI_PromptManager",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/ComfyAssets/ComfyUI_PromptManager"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A powerful ComfyUI custom node that extends the standard text encoder with persistent prompt storage, advanced search capabilities, and an automatic image gallery system using SQLite."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "TFL-TFL",
|
||||||
|
"title": "ComfyUI_Text_Translation",
|
||||||
|
"reference": "https://github.com/TFL-TFL/ComfyUI_Text_Translation",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/TFL-TFL/ComfyUI_Text_Translation"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Text translation node for ComfyUI: No need to apply for a translation API key, just use it. Currently supports more than thirty translation platforms."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Charonartist",
|
||||||
|
"title": "ComfyUI-EagleExporter",
|
||||||
|
"reference": "https://github.com/Charonartist/ComfyUI-EagleExporter",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/Charonartist/ComfyUI-EagleExporter"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "This is an extension that automatically saves video files generated with ComfyUI's 'video combine' extension to the Eagle library."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Charonartist",
|
||||||
|
"title": "Comfyui_gemini_tts_node",
|
||||||
|
"reference": "https://github.com/Charonartist/Comfyui_gemini_tts_node",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/Charonartist/Comfyui_gemini_tts_node"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "This custom node is a ComfyUI node for generating speech from text using the Gemini 2.5 Flash Preview TTS API."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "ptmaster",
|
||||||
|
"title": "ComfyUI-Load-Diffusion-Model-to-Muti-GPUs",
|
||||||
|
"reference": "https://github.com/ptmaster/ComfyUI-Load-Diffusion-Model-to-Muti-GPUs",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/ptmaster/ComfyUI-Load-Diffusion-Model-to-Muti-GPUs/raw/refs/heads/main/Load%20Diffusion%20Model%20into%20Muti%20GPUs.py"
|
||||||
|
],
|
||||||
|
"install_type": "copy",
|
||||||
|
"description": "NODES: OverrideLoadedDiffusionDevice.\nI happen to have two graphics cards, and I want to load models into another graphics card in Comfyui, so I designed this small node."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "ptmaster",
|
||||||
|
"title": "ComfyUI-audio-speed",
|
||||||
|
"reference": "https://github.com/ptmaster/comfyui-audio-speed",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/ptmaster/comfyui-audio-speed"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "This node pack is designed to adjust audio playback speed within ComfyUI, particularly to sync audio with models like FantasyTalking (WAN) that require specific frame rates. It can also be used for general-purpose audio speed control."
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -26168,17 +26510,6 @@
|
|||||||
"install_type": "copy",
|
"install_type": "copy",
|
||||||
"description": "Nodes:TextToSpeech, phy_3_conditioning, SaveAudioToDaVinci, SaveImageToDaVinci.\nNOTE:In order to use DaVinci node you must have DaVinci Resolve Studio connected to the API. For more information check the help seciton in DaVinci Resolve Studio HELP>DOCUMENTATION>DEVELOPER. It will open a folder, search for scripting and the for README.txt file, the API documentation."
|
"description": "Nodes:TextToSpeech, phy_3_conditioning, SaveAudioToDaVinci, SaveImageToDaVinci.\nNOTE:In order to use DaVinci node you must have DaVinci Resolve Studio connected to the API. For more information check the help seciton in DaVinci Resolve Studio HELP>DOCUMENTATION>DEVELOPER. It will open a folder, search for scripting and the for README.txt file, the API documentation."
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"author": "Limbicnation",
|
|
||||||
"title": "ComfyUIDepthEstimation",
|
|
||||||
"reference": "https://github.com/Limbicnation/ComfyUIDepthEstimation",
|
|
||||||
"files": [
|
|
||||||
"https://raw.githubusercontent.com/Limbicnation/ComfyUIDepthEstimation/main/depth_estimation_node.py"
|
|
||||||
],
|
|
||||||
"pip": ["transformers"],
|
|
||||||
"install_type": "copy",
|
|
||||||
"description": "A robust custom depth estimation node for ComfyUI using Depth-Anything models. It integrates depth estimation with configurable post-processing options including blur, median filtering, contrast enhancement, and gamma correction."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"author": "seghier",
|
"author": "seghier",
|
||||||
"title": "ComfyUI_LibreTranslate",
|
"title": "ComfyUI_LibreTranslate",
|
||||||
@@ -26240,16 +26571,6 @@
|
|||||||
"install_type": "copy",
|
"install_type": "copy",
|
||||||
"description": "Extremely inspired and forked from: [a/https://github.com/klimaleksus/stable-diffusion-webui-embedding-merge](https://github.com/klimaleksus/stable-diffusion-webui-embedding-merge)"
|
"description": "Extremely inspired and forked from: [a/https://github.com/klimaleksus/stable-diffusion-webui-embedding-merge](https://github.com/klimaleksus/stable-diffusion-webui-embedding-merge)"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"author": "ptmaster",
|
|
||||||
"title": "ComfyUI-Load-Diffusion-Model-to-Muti-GPUs",
|
|
||||||
"reference": "https://github.com/ptmaster/ComfyUI-Load-Diffusion-Model-to-Muti-GPUs",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/ptmaster/ComfyUI-Load-Diffusion-Model-to-Muti-GPUs/raw/refs/heads/main/Load%20Diffusion%20Model%20into%20Muti%20GPUs.py"
|
|
||||||
],
|
|
||||||
"install_type": "copy",
|
|
||||||
"description": "NODES: OverrideLoadedDiffusionDevice.\nI happen to have two graphics cards, and I want to load models into another graphics card in Comfyui, so I designed this small node."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"author": "Kayarte",
|
"author": "Kayarte",
|
||||||
"title": "GeoNodes",
|
"title": "GeoNodes",
|
||||||
|
|||||||
41
docs/README.md
Normal file
41
docs/README.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# ComfyUI-Manager: Documentation
|
||||||
|
|
||||||
|
This directory contains documentation for the ComfyUI-Manager, providing guides and tutorials for users in multiple languages.
|
||||||
|
|
||||||
|
## Directory Structure
|
||||||
|
|
||||||
|
The documentation is organized into language-specific directories:
|
||||||
|
|
||||||
|
- **en/**: English documentation
|
||||||
|
- **ko/**: Korean documentation
|
||||||
|
|
||||||
|
## Core Documentation Files
|
||||||
|
|
||||||
|
### Command-Line Interface
|
||||||
|
|
||||||
|
- **cm-cli.md**: Documentation for the ComfyUI-Manager Command Line Interface (CLI), which allows using manager functionality without the UI.
|
||||||
|
|
||||||
|
### Advanced Features
|
||||||
|
|
||||||
|
- **use_aria2.md**: Guide for using the aria2 download accelerator with ComfyUI-Manager for faster model downloads.
|
||||||
|
|
||||||
|
## Documentation Standards
|
||||||
|
|
||||||
|
The documentation follows these standards:
|
||||||
|
|
||||||
|
1. **Markdown Format**: All documentation is written in Markdown for easy rendering on GitHub and other platforms
|
||||||
|
2. **Language-specific Directories**: Content is separated by language to facilitate localization
|
||||||
|
3. **Feature-focused Documentation**: Each major feature has its own documentation file
|
||||||
|
4. **Updated with Releases**: Documentation is kept in sync with software releases
|
||||||
|
|
||||||
|
## Contributing to Documentation
|
||||||
|
|
||||||
|
When contributing new documentation:
|
||||||
|
|
||||||
|
1. Place files in the appropriate language directory
|
||||||
|
2. Use clear, concise language appropriate for the target audience
|
||||||
|
3. Include examples where helpful
|
||||||
|
4. Consider adding screenshots or diagrams for complex features
|
||||||
|
5. Maintain consistent formatting with existing documentation
|
||||||
|
|
||||||
|
This documentation directory will continue to grow to support the expanding feature set of ComfyUI-Manager.
|
||||||
File diff suppressed because it is too large
Load Diff
6405
github-stats.json
6405
github-stats.json
File diff suppressed because it is too large
Load Diff
53
glob/README.md
Normal file
53
glob/README.md
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# ComfyUI-Manager: Core Backend (glob)
|
||||||
|
|
||||||
|
This directory contains the Python backend modules that power ComfyUI-Manager, handling the core functionality of node management, downloading, security, and server operations.
|
||||||
|
|
||||||
|
## Core Modules
|
||||||
|
|
||||||
|
- **manager_core.py**: The central implementation of management functions, handling configuration, installation, updates, and node management.
|
||||||
|
- **manager_server.py**: Implements server functionality and API endpoints for the web interface to interact with the backend.
|
||||||
|
- **manager_downloader.py**: Handles downloading operations for models, extensions, and other resources.
|
||||||
|
- **manager_util.py**: Provides utility functions used throughout the system.
|
||||||
|
|
||||||
|
## Specialized Modules
|
||||||
|
|
||||||
|
- **cm_global.py**: Maintains global variables and state management across the system.
|
||||||
|
- **cnr_utils.py**: Helper utilities for interacting with the custom node registry (CNR).
|
||||||
|
- **git_utils.py**: Git-specific utilities for repository operations.
|
||||||
|
- **node_package.py**: Handles the packaging and installation of node extensions.
|
||||||
|
- **security_check.py**: Implements the multi-level security system for installation safety.
|
||||||
|
- **share_3rdparty.py**: Manages integration with third-party sharing platforms.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
The backend follows a modular design pattern with clear separation of concerns:
|
||||||
|
|
||||||
|
1. **Core Layer**: Manager modules provide the primary API and business logic
|
||||||
|
2. **Utility Layer**: Helper modules provide specialized functionality
|
||||||
|
3. **Integration Layer**: Modules that connect to external systems
|
||||||
|
|
||||||
|
## Security Model
|
||||||
|
|
||||||
|
The system implements a comprehensive security framework with multiple levels:
|
||||||
|
|
||||||
|
- **Block**: Highest security - blocks most remote operations
|
||||||
|
- **High**: Allows only specific trusted operations
|
||||||
|
- **Middle**: Standard security for most users
|
||||||
|
- **Normal-**: More permissive for advanced users
|
||||||
|
- **Weak**: Lowest security for development environments
|
||||||
|
|
||||||
|
## Implementation Details
|
||||||
|
|
||||||
|
- The backend is designed to work seamlessly with ComfyUI
|
||||||
|
- Asynchronous task queuing is implemented for background operations
|
||||||
|
- The system supports multiple installation modes
|
||||||
|
- Error handling and risk assessment are integrated throughout the codebase
|
||||||
|
|
||||||
|
## API Integration
|
||||||
|
|
||||||
|
The backend exposes a REST API via `manager_server.py` that enables:
|
||||||
|
- Custom node management (install, update, disable, remove)
|
||||||
|
- Model downloading and organization
|
||||||
|
- System configuration
|
||||||
|
- Snapshot management
|
||||||
|
- Workflow component handling
|
||||||
@@ -43,7 +43,7 @@ import manager_downloader
|
|||||||
from node_package import InstalledNodePackage
|
from node_package import InstalledNodePackage
|
||||||
|
|
||||||
|
|
||||||
version_code = [3, 32, 3]
|
version_code = [3, 32, 5]
|
||||||
version_str = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
|
version_str = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -437,7 +437,10 @@ async def task_worker():
|
|||||||
|
|
||||||
if res.ver == 'unknown':
|
if res.ver == 'unknown':
|
||||||
url = core.unified_manager.unknown_active_nodes[node_name][0]
|
url = core.unified_manager.unknown_active_nodes[node_name][0]
|
||||||
title = os.path.basename(url)
|
try:
|
||||||
|
title = os.path.basename(url)
|
||||||
|
except Exception:
|
||||||
|
title = node_name
|
||||||
else:
|
else:
|
||||||
url = core.unified_manager.cnr_map[node_name].get('repository')
|
url = core.unified_manager.cnr_map[node_name].get('repository')
|
||||||
title = core.unified_manager.cnr_map[node_name]['name']
|
title = core.unified_manager.cnr_map[node_name]['name']
|
||||||
|
|||||||
@@ -476,7 +476,7 @@ class PIPFixer:
|
|||||||
normalized_name = parsed['package'].lower().replace('-', '_')
|
normalized_name = parsed['package'].lower().replace('-', '_')
|
||||||
if normalized_name in new_pip_versions:
|
if normalized_name in new_pip_versions:
|
||||||
if 'version' in parsed and 'operator' in parsed:
|
if 'version' in parsed and 'operator' in parsed:
|
||||||
cur = StrictVersion(new_pip_versions[parsed['package']])
|
cur = StrictVersion(new_pip_versions[normalized_name])
|
||||||
dest = parsed['version']
|
dest = parsed['version']
|
||||||
op = parsed['operator']
|
op = parsed['operator']
|
||||||
if cur == dest:
|
if cur == dest:
|
||||||
|
|||||||
50
js/README.md
Normal file
50
js/README.md
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# ComfyUI-Manager: Frontend (js)
|
||||||
|
|
||||||
|
This directory contains the JavaScript frontend implementation for ComfyUI-Manager, providing the user interface components that interact with the backend API.
|
||||||
|
|
||||||
|
## Core Components
|
||||||
|
|
||||||
|
- **comfyui-manager.js**: Main entry point that initializes the manager UI and integrates with ComfyUI.
|
||||||
|
- **custom-nodes-manager.js**: Implements the UI for browsing, installing, and managing custom nodes.
|
||||||
|
- **model-manager.js**: Handles the model management interface for downloading and organizing AI models.
|
||||||
|
- **components-manager.js**: Manages reusable workflow components system.
|
||||||
|
- **snapshot.js**: Implements the snapshot system for backing up and restoring installations.
|
||||||
|
|
||||||
|
## Sharing Components
|
||||||
|
|
||||||
|
- **comfyui-share-common.js**: Base functionality for workflow sharing features.
|
||||||
|
- **comfyui-share-copus.js**: Integration with the ComfyUI Opus sharing platform.
|
||||||
|
- **comfyui-share-openart.js**: Integration with the OpenArt sharing platform.
|
||||||
|
- **comfyui-share-youml.js**: Integration with the YouML sharing platform.
|
||||||
|
|
||||||
|
## Utility Components
|
||||||
|
|
||||||
|
- **cm-api.js**: Client-side API wrapper for communication with the backend.
|
||||||
|
- **common.js**: Shared utilities and helper functions used across the frontend.
|
||||||
|
- **node_fixer.js**: Utilities for fixing disconnected links and repairing malformed nodes by recreating them while preserving connections.
|
||||||
|
- **popover-helper.js**: UI component for popup tooltips and contextual information.
|
||||||
|
- **turbogrid.esm.js**: Grid component library - https://github.com/cenfun/turbogrid
|
||||||
|
- **workflow-metadata.js**: Handles workflow metadata parsing, validation and cross-repository compatibility including versioning, dependencies tracking, and resource management.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
The frontend follows a modular component-based architecture:
|
||||||
|
|
||||||
|
1. **Integration Layer**: Connects with ComfyUI's existing UI system
|
||||||
|
2. **Manager Components**: Individual functional UI components (node manager, model manager, etc.)
|
||||||
|
3. **Sharing Components**: Platform-specific sharing implementations
|
||||||
|
4. **Utility Layer**: Reusable UI components and helpers
|
||||||
|
|
||||||
|
## Implementation Details
|
||||||
|
|
||||||
|
- The frontend integrates directly with ComfyUI's UI system through `app.js`
|
||||||
|
- Dialog-based UI for most manager functions to avoid cluttering the main interface
|
||||||
|
- Asynchronous API calls to handle backend operations without blocking the UI
|
||||||
|
|
||||||
|
## Styling
|
||||||
|
|
||||||
|
CSS files are included for specific components:
|
||||||
|
- **custom-nodes-manager.css**: Styling for the node management UI
|
||||||
|
- **model-manager.css**: Styling for the model management UI
|
||||||
|
|
||||||
|
This frontend implementation provides a comprehensive yet user-friendly interface for managing the ComfyUI ecosystem.
|
||||||
95
node_db/README.md
Normal file
95
node_db/README.md
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
# ComfyUI-Manager: Node Database (node_db)
|
||||||
|
|
||||||
|
This directory contains the JSON database files that power ComfyUI-Manager's legacy node registry system. While the manager is gradually transitioning to the online Custom Node Registry (CNR), these local JSON files continue to provide important metadata about custom nodes, models, and their integrations.
|
||||||
|
|
||||||
|
## Directory Structure
|
||||||
|
|
||||||
|
The node_db directory is organized into several subdirectories, each serving a specific purpose:
|
||||||
|
|
||||||
|
- **dev/**: Development channel files with latest additions and experimental nodes
|
||||||
|
- **legacy/**: Historical/legacy nodes that may require special handling
|
||||||
|
- **new/**: New nodes that have passed initial verification but are still being evaluated
|
||||||
|
- **forked/**: Forks of existing nodes with modifications
|
||||||
|
- **tutorial/**: Example and tutorial nodes designed for learning purposes
|
||||||
|
|
||||||
|
## Core Database Files
|
||||||
|
|
||||||
|
Each subdirectory contains a standard set of JSON files:
|
||||||
|
|
||||||
|
- **custom-node-list.json**: Primary database of custom nodes with metadata
|
||||||
|
- **extension-node-map.json**: Maps between extensions and individual nodes they provide
|
||||||
|
- **model-list.json**: Catalog of models that can be downloaded through the manager
|
||||||
|
- **alter-list.json**: Alternative implementations of nodes for compatibility or functionality
|
||||||
|
- **github-stats.json**: GitHub repository statistics for node popularity metrics
|
||||||
|
|
||||||
|
## Database Schema
|
||||||
|
|
||||||
|
### custom-node-list.json
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"custom_nodes": [
|
||||||
|
{
|
||||||
|
"title": "Node display name",
|
||||||
|
"name": "Repository name",
|
||||||
|
"reference": "Original repository if forked",
|
||||||
|
"files": ["GitHub URL or other source location"],
|
||||||
|
"install_type": "git",
|
||||||
|
"description": "Description of the node's functionality",
|
||||||
|
"pip": ["optional pip dependencies"],
|
||||||
|
"js": ["optional JavaScript files"],
|
||||||
|
"tags": ["categorization tags"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### extension-node-map.json
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"extension-id": [
|
||||||
|
["list", "of", "node", "classes"],
|
||||||
|
{
|
||||||
|
"author": "Author name",
|
||||||
|
"description": "Extension description",
|
||||||
|
"nodename_pattern": "Optional regex pattern for node name matching"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Transition to Custom Node Registry (CNR)
|
||||||
|
|
||||||
|
This local database system is being progressively replaced by the online Custom Node Registry (CNR), which provides:
|
||||||
|
- Real-time updates without manual JSON maintenance
|
||||||
|
- Improved versioning support
|
||||||
|
- Better security validation
|
||||||
|
- Enhanced metadata
|
||||||
|
|
||||||
|
The Manager supports both systems simultaneously during the transition period.
|
||||||
|
|
||||||
|
## Implementation Details
|
||||||
|
|
||||||
|
- The database follows a channel-based architecture for different sources
|
||||||
|
- Multiple database modes are supported: Channel, Local, and Remote
|
||||||
|
- The system supports differential updates to minimize bandwidth usage
|
||||||
|
- Security levels are enforced for different node installations based on source
|
||||||
|
|
||||||
|
## Usage in the Application
|
||||||
|
|
||||||
|
The Manager's backend uses these database files to:
|
||||||
|
|
||||||
|
1. Provide browsable lists of available nodes and models
|
||||||
|
2. Resolve dependencies for installation
|
||||||
|
3. Track updates and new versions
|
||||||
|
4. Map node classes to their source repositories
|
||||||
|
5. Assess risk levels for installation security
|
||||||
|
|
||||||
|
## Maintenance Scripts
|
||||||
|
|
||||||
|
Each subdirectory contains a `scan.sh` script that assists with:
|
||||||
|
- Scanning repositories for new nodes
|
||||||
|
- Updating metadata
|
||||||
|
- Validating database integrity
|
||||||
|
- Generating proper JSON structures
|
||||||
|
|
||||||
|
This database system enables a flexible, secure, and comprehensive management system for the ComfyUI ecosystem while the transition to CNR continues.
|
||||||
@@ -13,6 +13,120 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"author": "Charonartist",
|
||||||
|
"title": "ComfyUI-send-eagle-pro [WIP]",
|
||||||
|
"reference": "https://github.com/Charonartist/ComfyUI-send-eagle-pro",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/Charonartist/ComfyUI-send-eagle-pro"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "This is an extension node for ComfyUI that allows you to send generated images in webp format to [a/Eagle](https://en.eagle.cool/). This extension node is a re-implementation of the Eagle linkage functions of the previous [a/ComfyUI-send-Eagle](https://github.com/shingo1228/ComfyUI-send-eagle) node, focusing on the functions required for this node.\nNOTE: The files in the repo are not organized."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Mervent",
|
||||||
|
"title": "comfyui-yaml-prompt",
|
||||||
|
"reference": "https://github.com/Mervent/comfyui-yaml-prompt",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/Mervent/comfyui-yaml-prompt"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "NODES: YAMLPromptParser"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "dhpdong",
|
||||||
|
"title": "ComfyUI-IPAdapter-Flux-Repair",
|
||||||
|
"reference": "https://github.com/dhpdong/ComfyUI-IPAdapter-Flux-Repair",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/dhpdong/ComfyUI-IPAdapter-Flux-Repair"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "The IPAdapter-Flux node may cause some GPU memory to not be properly released during multiple inferences or when alternating between two nodes, eventually leading to a memory overflow. This project addresses and fixes that issue."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "usman2003",
|
||||||
|
"title": "ComfyUI-RaceDetect",
|
||||||
|
"reference": "https://github.com/usman2003/ComfyUI-RaceDetect",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/usman2003/ComfyUI-RaceDetect"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "NODES: Race Detection V2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Mervent",
|
||||||
|
"title": "comfyui-telegram-send",
|
||||||
|
"reference": "https://github.com/Mervent/comfyui-telegram-send",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/Mervent/comfyui-telegram-send"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "NODES: TelegramSend, TelegramReply"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "qlikpetersen",
|
||||||
|
"title": "ComfyUI-AI_Tools [UNSAFE]",
|
||||||
|
"reference": "https://github.com/qlikpetersen/ComfyUI-AI_Tools",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/qlikpetersen/ComfyUI-AI_Tools"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "NODES: DoLogin, HttpRequest, Json2String, String2Json, CreateListString, CreateListJSON, Query_OpenAI, Image_Attachment, JSON_Attachment, String_Attachment, RunPython\n[w/This node pack contains a node with a vulnerability that allows arbitrary code execution.]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "MuAIGC",
|
||||||
|
"title": "DMXAPI Nodes",
|
||||||
|
"reference": "https://github.com/MuAIGC/ComfyUI-DMXAPI_mmx",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/MuAIGC/ComfyUI-DMXAPI_mmx"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "DMXAPI integration for ComfyUI with Seedream-3.0 text-to-image model"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Hapseleg",
|
||||||
|
"title": "This n that (Hapse)",
|
||||||
|
"reference": "https://github.com/Hapseleg/ComfyUI-This-n-That",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/Hapseleg/ComfyUI-This-n-That"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Comfyui custom nodes I use for... This n That..."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "matDobek",
|
||||||
|
"title": "ComfyUI_duck",
|
||||||
|
"reference": "https://github.com/matDobek/ComfyUI_duck",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/matDobek/ComfyUI_duck"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "NODES: Combine Images (duck)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "usman2003",
|
||||||
|
"title": "ComfyUI-Classifiers",
|
||||||
|
"reference": "https://github.com/usman2003/ComfyUI-Classifiers",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/usman2003/ComfyUI-Classifiers"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "NODES: Gender Classification"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "wTechArtist",
|
||||||
|
"title": "ComfyUI_vvl_BBOX",
|
||||||
|
"reference": "https://github.com/wTechArtist/ComfyUI_vvl_BBOX",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/wTechArtist/ComfyUI_vvl_BBOX"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "NODES: vvl BBox Input"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "zhengxyz123",
|
"author": "zhengxyz123",
|
||||||
"title": "zhengxyz123/ComfyUI-CLIPSeg [NAME CONFLICT]",
|
"title": "zhengxyz123/ComfyUI-CLIPSeg [NAME CONFLICT]",
|
||||||
@@ -43,16 +157,6 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Some ComfyUI nodes to fetch cards from scryfall"
|
"description": "Some ComfyUI nodes to fetch cards from scryfall"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"author": "pomePLaszlo-collablyu",
|
|
||||||
"title": "comfyui_ejam",
|
|
||||||
"reference": "https://github.com/PLaszlo-collab/comfyui_ejam",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/PLaszlo-collab/comfyui_ejam"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Ejam nodes for comfyui"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"author": "pomelyu",
|
"author": "pomelyu",
|
||||||
"title": "cy-prompt-tools",
|
"title": "cy-prompt-tools",
|
||||||
@@ -143,16 +247,6 @@
|
|||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "this node lists json files in the ComfyUI input folder[w/If this node pack is installed and the server is running with remote access enabled, it can read the contents of JSON files located in arbitrary paths.]"
|
"description": "this node lists json files in the ComfyUI input folder[w/If this node pack is installed and the server is running with remote access enabled, it can read the contents of JSON files located in arbitrary paths.]"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"author": "silveroxides",
|
|
||||||
"title": "ComfyUI_EmbeddingToolkit",
|
|
||||||
"reference": "https://github.com/silveroxides/ComfyUI_EmbeddingToolkit",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/silveroxides/ComfyUI_EmbeddingToolkit"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "NODES: Save Token Embeddings, Save Weighted Embeddings, Save A1111-style Weighted Embeddings"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"author": "yichengup",
|
"author": "yichengup",
|
||||||
"title": "ComfyUI-YCNodes_Advance",
|
"title": "ComfyUI-YCNodes_Advance",
|
||||||
@@ -195,7 +289,6 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "virallover",
|
"author": "virallover",
|
||||||
"title": "comfyui-virallover",
|
|
||||||
"reference": "https://github.com/maizerrr/comfyui-code-nodes",
|
"reference": "https://github.com/maizerrr/comfyui-code-nodes",
|
||||||
"files": [
|
"files": [
|
||||||
"https://github.com/maizerrr/comfyui-code-nodes"
|
"https://github.com/maizerrr/comfyui-code-nodes"
|
||||||
@@ -211,7 +304,7 @@
|
|||||||
"https://github.com/virallover/comfyui-virallover"
|
"https://github.com/virallover/comfyui-virallover"
|
||||||
],
|
],
|
||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "NODES: Download and Load Lora Model Only"
|
"description": "NODES: Download and Load Lora Model Only, Depth Fitter, Brightness Correction, Edge Noise, Feathered Sharpen"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "nobandegani",
|
"author": "nobandegani",
|
||||||
@@ -601,7 +694,7 @@
|
|||||||
"https://github.com/jtydhr88/ComfyUI_frontend_vue_basic"
|
"https://github.com/jtydhr88/ComfyUI_frontend_vue_basic"
|
||||||
],
|
],
|
||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "ComfyUI Frontend Vue Basic is custom node that demonstrate how to use vue as frontend framework along with primevue and vue-i18n, cooperating with ComfyUI API"
|
"description": "A demonstration custom node that showcases how to integrate Vue as a frontend framework within ComfyUI, complete with PrimeVue components and vue-i18n support."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "silent-rain",
|
"author": "silent-rain",
|
||||||
@@ -2917,16 +3010,6 @@
|
|||||||
],
|
],
|
||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "A set of nodes to edit videos using the Hunyuan Video model"
|
"description": "A set of nodes to edit videos using the Hunyuan Video model"
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "jonnydolake",
|
|
||||||
"title": "ComfyUI-AIR-Nodes",
|
|
||||||
"reference": "https://github.com/jonnydolake/ComfyUI-AIR-Nodes",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/jonnydolake/ComfyUI-AIR-Nodes"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "NODES: String List To Prompt Schedule, Force Minimum Batch Size, Target Location (Crop), Target Location (Paste), Image Composite Chained, Match Image Count To Mask Count, Random Character Prompts, Parallax Test, Easy Parallax, Parallax GPU Test"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"author": "watarika",
|
"author": "watarika",
|
||||||
|
|||||||
@@ -149,10 +149,11 @@
|
|||||||
"https://github.com/1hew/ComfyUI-1hewNodes": [
|
"https://github.com/1hew/ComfyUI-1hewNodes": [
|
||||||
[
|
[
|
||||||
"BlendModesAlpha",
|
"BlendModesAlpha",
|
||||||
"CoordinateExtractor",
|
"CoordinateExtract",
|
||||||
"ImageAddLabel",
|
"ImageAddLabel",
|
||||||
"ImageBBoxCrop",
|
"ImageBBoxCrop",
|
||||||
"ImageBlendModesByCSS",
|
"ImageBlendModesByCSS",
|
||||||
|
"ImageCropEdge",
|
||||||
"ImageCropSquare",
|
"ImageCropSquare",
|
||||||
"ImageCropWithBBox",
|
"ImageCropWithBBox",
|
||||||
"ImageCroppedPaste",
|
"ImageCroppedPaste",
|
||||||
@@ -164,6 +165,8 @@
|
|||||||
"MaskBBoxCrop",
|
"MaskBBoxCrop",
|
||||||
"MaskBatchMathOps",
|
"MaskBatchMathOps",
|
||||||
"MaskMathOps",
|
"MaskMathOps",
|
||||||
|
"PathSelect",
|
||||||
|
"PromptExtract",
|
||||||
"SliderValueRangeMapping",
|
"SliderValueRangeMapping",
|
||||||
"Solid"
|
"Solid"
|
||||||
],
|
],
|
||||||
@@ -594,6 +597,15 @@
|
|||||||
"title_aux": "ComfyUI-Tools"
|
"title_aux": "ComfyUI-Tools"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/Alazuaka/comfyui-lora-stack-node": [
|
||||||
|
[
|
||||||
|
"EsCheckpointSet",
|
||||||
|
"EsLoraSet"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "ES_nodes for ComfyUI by Alazuka [WIP]"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/AlejandroTuzzi/TUZZI-ByPass": [
|
"https://github.com/AlejandroTuzzi/TUZZI-ByPass": [
|
||||||
[
|
[
|
||||||
"LinkSuppressor",
|
"LinkSuppressor",
|
||||||
@@ -915,6 +927,19 @@
|
|||||||
"title_aux": "ComfyUI-vts-nodes [WIP]"
|
"title_aux": "ComfyUI-vts-nodes [WIP]"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/Charonartist/ComfyUI-send-eagle-pro": [
|
||||||
|
[
|
||||||
|
"Batch Send Media to Eagle",
|
||||||
|
"Send Audio to Eagle",
|
||||||
|
"Send Eagle with text",
|
||||||
|
"Send Media to Eagle",
|
||||||
|
"Send Video to Eagle",
|
||||||
|
"Send Webp Image to Eagle"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "ComfyUI-send-eagle-pro [WIP]"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/ChrisColeTech/ComfyUI-Get-Random-File": [
|
"https://github.com/ChrisColeTech/ComfyUI-Get-Random-File": [
|
||||||
[
|
[
|
||||||
"Get Image File By Index",
|
"Get Image File By Index",
|
||||||
@@ -1067,10 +1092,20 @@
|
|||||||
"Donut Detailer 4",
|
"Donut Detailer 4",
|
||||||
"Donut Detailer LoRA 5",
|
"Donut Detailer LoRA 5",
|
||||||
"Donut Detailer XL Blocks",
|
"Donut Detailer XL Blocks",
|
||||||
|
"DonutAppendClipToList",
|
||||||
|
"DonutAppendModelToList",
|
||||||
"DonutApplyLoRAStack",
|
"DonutApplyLoRAStack",
|
||||||
"DonutClipEncode",
|
"DonutClipEncode",
|
||||||
"DonutLoRAStack",
|
"DonutLoRAStack",
|
||||||
|
"DonutLoadCLIPModels",
|
||||||
|
"DonutLoadUNetModels",
|
||||||
|
"DonutMakeClipList2",
|
||||||
|
"DonutMakeModelList2",
|
||||||
|
"DonutMergeClipLists",
|
||||||
|
"DonutMergeModelLists",
|
||||||
"DonutWidenMerge",
|
"DonutWidenMerge",
|
||||||
|
"DonutWidenMergeCLIP",
|
||||||
|
"DonutWidenMergeUNet",
|
||||||
"LoadLBW //Inspire",
|
"LoadLBW //Inspire",
|
||||||
"LoraBlockInfo //Inspire",
|
"LoraBlockInfo //Inspire",
|
||||||
"LoraLoaderBlockWeight //Inspire",
|
"LoraLoaderBlockWeight //Inspire",
|
||||||
@@ -1362,6 +1397,19 @@
|
|||||||
"title_aux": "GH Tools for ComfyUI"
|
"title_aux": "GH Tools for ComfyUI"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/Hapseleg/ComfyUI-This-n-That": [
|
||||||
|
[
|
||||||
|
"Show Prompt (Hapse)",
|
||||||
|
"Show Prompt TnT",
|
||||||
|
"Simple Ratio Selector (Hapse)",
|
||||||
|
"Simple Ratio Selector TnT",
|
||||||
|
"Simple Seed Selector (Hapse)",
|
||||||
|
"Simple Seed Selector TnT"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "This n that (Hapse)"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/HuangYuChuh/ComfyUI-DeepSeek-Toolkit": [
|
"https://github.com/HuangYuChuh/ComfyUI-DeepSeek-Toolkit": [
|
||||||
[
|
[
|
||||||
"DeepSeekImageAnalyst",
|
"DeepSeekImageAnalyst",
|
||||||
@@ -1833,6 +1881,23 @@
|
|||||||
"title_aux": "ComfyUI-MS_Tools [WIP]"
|
"title_aux": "ComfyUI-MS_Tools [WIP]"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/Mervent/comfyui-telegram-send": [
|
||||||
|
[
|
||||||
|
"TelegramReply",
|
||||||
|
"TelegramSend"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "comfyui-telegram-send"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"https://github.com/Mervent/comfyui-yaml-prompt": [
|
||||||
|
[
|
||||||
|
"YAMLPromptParser"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "comfyui-yaml-prompt"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/MicheleGuidi/comfyui-computer-vision": [
|
"https://github.com/MicheleGuidi/comfyui-computer-vision": [
|
||||||
[
|
[
|
||||||
"Sam2ContextSegmentation",
|
"Sam2ContextSegmentation",
|
||||||
@@ -1894,6 +1959,16 @@
|
|||||||
"title_aux": "CheckProgress [WIP]"
|
"title_aux": "CheckProgress [WIP]"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/MuAIGC/ComfyUI-DMXAPI_mmx": [
|
||||||
|
[
|
||||||
|
"DMXAPIClient",
|
||||||
|
"DMXAPISaveImage",
|
||||||
|
"DMXAPITextToImage"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "DMXAPI Nodes"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/MythicalChu/ComfyUI-APG_ImYourCFGNow": [
|
"https://github.com/MythicalChu/ComfyUI-APG_ImYourCFGNow": [
|
||||||
[
|
[
|
||||||
"APG_ImYourCFGNow"
|
"APG_ImYourCFGNow"
|
||||||
@@ -2012,6 +2087,15 @@
|
|||||||
"title_aux": "ComfyUI-Sa2VAWrapper [WIP]"
|
"title_aux": "ComfyUI-Sa2VAWrapper [WIP]"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/PabloGrant/comfyui-giraffe-test-panel": [
|
||||||
|
[
|
||||||
|
"DebugHelloNode",
|
||||||
|
"GiraffeTestPanel"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "comfyui-giraffe-test-panel"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/Poseidon-fan/ComfyUI-fileCleaner": [
|
"https://github.com/Poseidon-fan/ComfyUI-fileCleaner": [
|
||||||
[
|
[
|
||||||
"Clean input and output file"
|
"Clean input and output file"
|
||||||
@@ -2520,6 +2604,27 @@
|
|||||||
"title_aux": "TWanVideoSigmaSampler: EXPERIMENTAL [WIP]"
|
"title_aux": "TWanVideoSigmaSampler: EXPERIMENTAL [WIP]"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/ThatGlennD/ComfyUI-Image-Analysis-Tools": [
|
||||||
|
[
|
||||||
|
"Blur Detection",
|
||||||
|
"Clipping Analysis",
|
||||||
|
"Color Cast Detector",
|
||||||
|
"Color Harmony Analyzer",
|
||||||
|
"Color Temperature Estimator",
|
||||||
|
"ColorTemperatureEstimator",
|
||||||
|
"Contrast Analysis",
|
||||||
|
"ContrastAnalysis",
|
||||||
|
"Defocus Analysis",
|
||||||
|
"Edge Density Analysis",
|
||||||
|
"Entropy Analysis",
|
||||||
|
"Noise Estimation",
|
||||||
|
"RGB Histogram Renderer",
|
||||||
|
"Sharpness / Focus Score"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "ComfyUI Image Analysis Toolkit [WIP]"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/TheJorseman/IntrinsicCompositingClean-ComfyUI": [
|
"https://github.com/TheJorseman/IntrinsicCompositingClean-ComfyUI": [
|
||||||
[
|
[
|
||||||
"AlbedoHarmonizer",
|
"AlbedoHarmonizer",
|
||||||
@@ -2803,6 +2908,7 @@
|
|||||||
],
|
],
|
||||||
"https://github.com/alexgenovese/ComfyUI-Reica": [
|
"https://github.com/alexgenovese/ComfyUI-Reica": [
|
||||||
[
|
[
|
||||||
|
"InsertAnythingNode",
|
||||||
"ReicaGCPReadImageNode",
|
"ReicaGCPReadImageNode",
|
||||||
"ReicaGCPWriteImageNode",
|
"ReicaGCPWriteImageNode",
|
||||||
"ReicaHTTPNotification",
|
"ReicaHTTPNotification",
|
||||||
@@ -3973,6 +4079,16 @@
|
|||||||
"title_aux": "comfyui-stylegan"
|
"title_aux": "comfyui-stylegan"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/dhpdong/ComfyUI-IPAdapter-Flux-Repair": [
|
||||||
|
[
|
||||||
|
"SamplerCustomAdvancedPlus",
|
||||||
|
"SeedPlus",
|
||||||
|
"UnetLoaderGGUFPlus"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "ComfyUI-IPAdapter-Flux-Repair"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/dihan/comfyui-random-kps": [
|
"https://github.com/dihan/comfyui-random-kps": [
|
||||||
[
|
[
|
||||||
"RandomFaceKeypoints"
|
"RandomFaceKeypoints"
|
||||||
@@ -4122,6 +4238,14 @@
|
|||||||
"title_aux": "guidance_interval"
|
"title_aux": "guidance_interval"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/erosDiffusion/ComfyUI-enricos-json-file-load-and-value-selector": [
|
||||||
|
[
|
||||||
|
"SelectorNode"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "Select key from JSON (Alpha) [UNSAFE]"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/esciron/ComfyUI-HunyuanVideoWrapper-Extended": [
|
"https://github.com/esciron/ComfyUI-HunyuanVideoWrapper-Extended": [
|
||||||
[
|
[
|
||||||
"DownloadAndLoadHyVideoTextEncoder",
|
"DownloadAndLoadHyVideoTextEncoder",
|
||||||
@@ -4371,6 +4495,15 @@
|
|||||||
"title_aux": "comfyui-custom-padding"
|
"title_aux": "comfyui-custom-padding"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/gordon123/ComfyUI_DreamBoard": [
|
||||||
|
[
|
||||||
|
"PromptExtraNode",
|
||||||
|
"StoryboardNode"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "ComfyUI_DreamBoard [WIP]"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/gordon123/ComfyUI_srt2speech": [
|
"https://github.com/gordon123/ComfyUI_srt2speech": [
|
||||||
[
|
[
|
||||||
"GetSubtitleByIndex",
|
"GetSubtitleByIndex",
|
||||||
@@ -4423,9 +4556,12 @@
|
|||||||
"XIS_LoadImage",
|
"XIS_LoadImage",
|
||||||
"XIS_MaskBatchProcessor",
|
"XIS_MaskBatchProcessor",
|
||||||
"XIS_MaskCompositeOperation",
|
"XIS_MaskCompositeOperation",
|
||||||
|
"XIS_MultiPromptSwitch",
|
||||||
|
"XIS_PSDLayerExtractor",
|
||||||
"XIS_PromptProcessor",
|
"XIS_PromptProcessor",
|
||||||
"XIS_PromptsWithSwitches",
|
"XIS_PromptsWithSwitches",
|
||||||
"XIS_ReorderImageMaskGroups",
|
"XIS_ReorderImageMaskGroups",
|
||||||
|
"XIS_ReorderImages",
|
||||||
"XIS_ResizeImageOrMask",
|
"XIS_ResizeImageOrMask",
|
||||||
"XIS_ResizeToDivisible",
|
"XIS_ResizeToDivisible",
|
||||||
"XIS_ResolutionSelector"
|
"XIS_ResolutionSelector"
|
||||||
@@ -4988,41 +5124,6 @@
|
|||||||
"title_aux": "jn_node_suite_comfyui [WIP]"
|
"title_aux": "jn_node_suite_comfyui [WIP]"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"https://github.com/jonnydolake/ComfyUI-AIR-Nodes": [
|
|
||||||
[
|
|
||||||
"BatchListToFlatList",
|
|
||||||
"BrightnessContrastSaturation",
|
|
||||||
"CombinedInbetweenInputs",
|
|
||||||
"CreateFilenameList",
|
|
||||||
"DetectEvenNumberString",
|
|
||||||
"DisplaceImageCPU",
|
|
||||||
"DisplaceImageGPU",
|
|
||||||
"ExtractBlackLines",
|
|
||||||
"FlatListToBatchList",
|
|
||||||
"ForceMinimumBatchSize",
|
|
||||||
"GPUTargetLocationCrop",
|
|
||||||
"GPUTargetLocationPaste",
|
|
||||||
"GetImageFromList",
|
|
||||||
"ImageCompositeChained",
|
|
||||||
"JoinImageLists",
|
|
||||||
"JoinStringLists",
|
|
||||||
"LTXVAddGuideAIR",
|
|
||||||
"LineDetection",
|
|
||||||
"MangaPanelSegmentationNode",
|
|
||||||
"Mask_Fill_Region",
|
|
||||||
"MatchImageCountToMaskCount",
|
|
||||||
"ParallaxTest",
|
|
||||||
"RandomCharacterPrompts",
|
|
||||||
"RemoveElementFromList",
|
|
||||||
"TargetLocationCrop",
|
|
||||||
"TargetLocationPaste",
|
|
||||||
"easy_parallax",
|
|
||||||
"string_list_to_prompt_schedule"
|
|
||||||
],
|
|
||||||
{
|
|
||||||
"title_aux": "ComfyUI-AIR-Nodes"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://github.com/jordancoult/ComfyUI_HelpfulNodes": [
|
"https://github.com/jordancoult/ComfyUI_HelpfulNodes": [
|
||||||
[
|
[
|
||||||
"JCo_CropAroundKPS"
|
"JCo_CropAroundKPS"
|
||||||
@@ -5113,6 +5214,7 @@
|
|||||||
[
|
[
|
||||||
"DITConfig",
|
"DITConfig",
|
||||||
"InferenceArgs",
|
"InferenceArgs",
|
||||||
|
"LoadImagePath",
|
||||||
"TextEncoderConfig",
|
"TextEncoderConfig",
|
||||||
"VAEConfig",
|
"VAEConfig",
|
||||||
"VideoGenerator"
|
"VideoGenerator"
|
||||||
@@ -5719,6 +5821,16 @@
|
|||||||
"title_aux": "xcpNodes [WIP]"
|
"title_aux": "xcpNodes [WIP]"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/lrzjason/Comfyui-Condition-Utils": [
|
||||||
|
[
|
||||||
|
"LoadCondition",
|
||||||
|
"LoadConditionFromLoras",
|
||||||
|
"SaveCondition"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "Comfyui-Condition-Utils [WIP]"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/ltdrdata/ComfyUI-Workflow-Component": [
|
"https://github.com/ltdrdata/ComfyUI-Workflow-Component": [
|
||||||
[
|
[
|
||||||
"ComboToString",
|
"ComboToString",
|
||||||
@@ -5761,10 +5873,12 @@
|
|||||||
"https://github.com/lucafoscili/lf-nodes": [
|
"https://github.com/lucafoscili/lf-nodes": [
|
||||||
[
|
[
|
||||||
"LF_Blend",
|
"LF_Blend",
|
||||||
|
"LF_BlobToImage",
|
||||||
"LF_Bloom",
|
"LF_Bloom",
|
||||||
"LF_BlurImages",
|
"LF_BlurImages",
|
||||||
"LF_Boolean",
|
"LF_Boolean",
|
||||||
"LF_Brightness",
|
"LF_Brightness",
|
||||||
|
"LF_CaptionImageWD14",
|
||||||
"LF_CharacterImpersonator",
|
"LF_CharacterImpersonator",
|
||||||
"LF_CheckpointSelector",
|
"LF_CheckpointSelector",
|
||||||
"LF_CivitAIMetadataSetup",
|
"LF_CivitAIMetadataSetup",
|
||||||
@@ -5773,6 +5887,7 @@
|
|||||||
"LF_CompareImages",
|
"LF_CompareImages",
|
||||||
"LF_Contrast",
|
"LF_Contrast",
|
||||||
"LF_ControlPanel",
|
"LF_ControlPanel",
|
||||||
|
"LF_CreateMask",
|
||||||
"LF_Desaturation",
|
"LF_Desaturation",
|
||||||
"LF_DisplayBoolean",
|
"LF_DisplayBoolean",
|
||||||
"LF_DisplayFloat",
|
"LF_DisplayFloat",
|
||||||
@@ -5781,6 +5896,7 @@
|
|||||||
"LF_DisplayPrimitiveAsJSON",
|
"LF_DisplayPrimitiveAsJSON",
|
||||||
"LF_DisplayString",
|
"LF_DisplayString",
|
||||||
"LF_EmbeddingSelector",
|
"LF_EmbeddingSelector",
|
||||||
|
"LF_EmptyImage",
|
||||||
"LF_ExtractPromptFromLoraTag",
|
"LF_ExtractPromptFromLoraTag",
|
||||||
"LF_ExtractString",
|
"LF_ExtractString",
|
||||||
"LF_FilmGrain",
|
"LF_FilmGrain",
|
||||||
@@ -5791,6 +5907,7 @@
|
|||||||
"LF_ImageClassifier",
|
"LF_ImageClassifier",
|
||||||
"LF_ImageHistogram",
|
"LF_ImageHistogram",
|
||||||
"LF_ImageListFromJSON",
|
"LF_ImageListFromJSON",
|
||||||
|
"LF_ImageToSVG",
|
||||||
"LF_ImagesEditingBreakpoint",
|
"LF_ImagesEditingBreakpoint",
|
||||||
"LF_ImagesSlideshow",
|
"LF_ImagesSlideshow",
|
||||||
"LF_Integer",
|
"LF_Integer",
|
||||||
@@ -5803,11 +5920,13 @@
|
|||||||
"LF_LUTGeneration",
|
"LF_LUTGeneration",
|
||||||
"LF_Line",
|
"LF_Line",
|
||||||
"LF_LoadAndEditImages",
|
"LF_LoadAndEditImages",
|
||||||
|
"LF_LoadCLIPSegModel",
|
||||||
"LF_LoadFileOnce",
|
"LF_LoadFileOnce",
|
||||||
"LF_LoadImages",
|
"LF_LoadImages",
|
||||||
"LF_LoadLocalJSON",
|
"LF_LoadLocalJSON",
|
||||||
"LF_LoadLoraTags",
|
"LF_LoadLoraTags",
|
||||||
"LF_LoadMetadata",
|
"LF_LoadMetadata",
|
||||||
|
"LF_LoadWD14Model",
|
||||||
"LF_LoraAndEmbeddingSelector",
|
"LF_LoraAndEmbeddingSelector",
|
||||||
"LF_LoraSelector",
|
"LF_LoraSelector",
|
||||||
"LF_MarkdownDocGenerator",
|
"LF_MarkdownDocGenerator",
|
||||||
@@ -5823,6 +5942,7 @@
|
|||||||
"LF_ResizeImageToSquare",
|
"LF_ResizeImageToSquare",
|
||||||
"LF_ResolutionSwitcher",
|
"LF_ResolutionSwitcher",
|
||||||
"LF_SamplerSelector",
|
"LF_SamplerSelector",
|
||||||
|
"LF_Saturation",
|
||||||
"LF_SaveImageForCivitAI",
|
"LF_SaveImageForCivitAI",
|
||||||
"LF_SaveJSON",
|
"LF_SaveJSON",
|
||||||
"LF_SaveMarkdown",
|
"LF_SaveMarkdown",
|
||||||
@@ -5852,6 +5972,7 @@
|
|||||||
"LF_UrandomSeedGenerator",
|
"LF_UrandomSeedGenerator",
|
||||||
"LF_UsageStatistics",
|
"LF_UsageStatistics",
|
||||||
"LF_VAESelector",
|
"LF_VAESelector",
|
||||||
|
"LF_Vibrance",
|
||||||
"LF_ViewImages",
|
"LF_ViewImages",
|
||||||
"LF_Vignette",
|
"LF_Vignette",
|
||||||
"LF_WallOfText",
|
"LF_WallOfText",
|
||||||
@@ -5898,7 +6019,7 @@
|
|||||||
"OpenAIQueryNode"
|
"OpenAIQueryNode"
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
"title_aux": "comfyui-virallover"
|
"title_aux": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"https://github.com/majorsauce/comfyui_indieTools": [
|
"https://github.com/majorsauce/comfyui_indieTools": [
|
||||||
@@ -5981,6 +6102,14 @@
|
|||||||
"title_aux": "ComfyUI-MMYolo"
|
"title_aux": "ComfyUI-MMYolo"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/matDobek/ComfyUI_duck": [
|
||||||
|
[
|
||||||
|
"Combine Images (duck)"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "ComfyUI_duck"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/maurorilla/ComfyUI-MisterMR-Nodes": [
|
"https://github.com/maurorilla/ComfyUI-MisterMR-Nodes": [
|
||||||
[
|
[
|
||||||
"AddLogo",
|
"AddLogo",
|
||||||
@@ -6514,6 +6643,18 @@
|
|||||||
"title_aux": "NudeNet-Detector-Provider [WIP]"
|
"title_aux": "NudeNet-Detector-Provider [WIP]"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/pomelyu/cy-prompt-tools": [
|
||||||
|
[
|
||||||
|
"CY_LoadPrompt",
|
||||||
|
"CY_LoadPrompt4",
|
||||||
|
"CY_LoadPromptPro",
|
||||||
|
"CY_PromptComposer",
|
||||||
|
"CY_TextBox"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "cy-prompt-tools"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/power88/ComfyUI-PDiD-Nodes": [
|
"https://github.com/power88/ComfyUI-PDiD-Nodes": [
|
||||||
[
|
[
|
||||||
"Blend Images",
|
"Blend Images",
|
||||||
@@ -6572,6 +6713,24 @@
|
|||||||
"title_aux": "comfyui-sd3-simple-simpletuner"
|
"title_aux": "comfyui-sd3-simple-simpletuner"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/qlikpetersen/ComfyUI-AI_Tools": [
|
||||||
|
[
|
||||||
|
"CreateListJSON",
|
||||||
|
"CreateListString",
|
||||||
|
"DoLogin",
|
||||||
|
"HttpRequest",
|
||||||
|
"Image_Attachment",
|
||||||
|
"JSON_Attachment",
|
||||||
|
"Json2String",
|
||||||
|
"Query_OpenAI",
|
||||||
|
"RunPython",
|
||||||
|
"String2Json",
|
||||||
|
"String_Attachment"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "ComfyUI-AI_Tools [UNSAFE]"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/rakki194/ComfyUI_WolfSigmas": [
|
"https://github.com/rakki194/ComfyUI_WolfSigmas": [
|
||||||
[
|
[
|
||||||
"GetImageSize",
|
"GetImageSize",
|
||||||
@@ -6580,10 +6739,10 @@
|
|||||||
"ModifyActivationsSVD",
|
"ModifyActivationsSVD",
|
||||||
"VisualizeActivation",
|
"VisualizeActivation",
|
||||||
"WolfDCTNoise",
|
"WolfDCTNoise",
|
||||||
"WolfDCTNoiseScriptableLatent",
|
|
||||||
"WolfPlotSamplerStatsNode",
|
"WolfPlotSamplerStatsNode",
|
||||||
"WolfProbeGetData",
|
"WolfProbeGetData",
|
||||||
"WolfProbeSetup",
|
"WolfProbeSetup",
|
||||||
|
"WolfSamplerCustomAdvancedPlotter",
|
||||||
"WolfSamplerScriptEvaluator",
|
"WolfSamplerScriptEvaluator",
|
||||||
"WolfScriptableEmptyLatent",
|
"WolfScriptableEmptyLatent",
|
||||||
"WolfScriptableLatentAnalyzer",
|
"WolfScriptableLatentAnalyzer",
|
||||||
@@ -7218,17 +7377,6 @@
|
|||||||
"title_aux": "_topfun_s_nodes"
|
"title_aux": "_topfun_s_nodes"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"https://github.com/thedivergentai/divergent_nodes": [
|
|
||||||
[
|
|
||||||
"CLIPTokenCounter",
|
|
||||||
"GeminiNode",
|
|
||||||
"KoboldCppApiNode",
|
|
||||||
"LoraStrengthXYPlot"
|
|
||||||
],
|
|
||||||
{
|
|
||||||
"title_aux": "Divergent Nodes [WIP]"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"https://github.com/threadedblue/MLXnodes": [
|
"https://github.com/threadedblue/MLXnodes": [
|
||||||
[
|
[
|
||||||
"MLXImg2Img",
|
"MLXImg2Img",
|
||||||
@@ -7281,6 +7429,17 @@
|
|||||||
"title_aux": "comfyui-p5js-node"
|
"title_aux": "comfyui-p5js-node"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/trampolin/comfy-ui-scryfall": [
|
||||||
|
[
|
||||||
|
"ScryfallCardInfoNode",
|
||||||
|
"ScryfallDecklistParserNode",
|
||||||
|
"ScryfallImageExtractorNode",
|
||||||
|
"ScryfallSearchNode"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "comfy-ui-scryfall"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/trashgraphicard/Albedo-Sampler-for-ComfyUI": [
|
"https://github.com/trashgraphicard/Albedo-Sampler-for-ComfyUI": [
|
||||||
[
|
[
|
||||||
"Make Seamless Tile",
|
"Make Seamless Tile",
|
||||||
@@ -7360,6 +7519,22 @@
|
|||||||
"title_aux": "ComfyUI-Dist [WIP]"
|
"title_aux": "ComfyUI-Dist [WIP]"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/usman2003/ComfyUI-Classifiers": [
|
||||||
|
[
|
||||||
|
"GenderClassificationNode"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "ComfyUI-Classifiers"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"https://github.com/usman2003/ComfyUI-RaceDetect": [
|
||||||
|
[
|
||||||
|
"RaceDetectionNodeV2"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "ComfyUI-RaceDetect"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/var1ableX/ComfyUI_Accessories": [
|
"https://github.com/var1ableX/ComfyUI_Accessories": [
|
||||||
[
|
[
|
||||||
"ACC_AnyCast",
|
"ACC_AnyCast",
|
||||||
@@ -7383,7 +7558,11 @@
|
|||||||
],
|
],
|
||||||
"https://github.com/virallover/comfyui-virallover": [
|
"https://github.com/virallover/comfyui-virallover": [
|
||||||
[
|
[
|
||||||
"DownloadAndLoadLoraModelOnly"
|
"BrightnessCorrectionNode",
|
||||||
|
"DepthFitter",
|
||||||
|
"DownloadAndLoadLoraModelOnly",
|
||||||
|
"EdgeNoise",
|
||||||
|
"FeatheredSharpen"
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
"title_aux": "comfyui-virallover"
|
"title_aux": "comfyui-virallover"
|
||||||
@@ -7400,12 +7579,22 @@
|
|||||||
],
|
],
|
||||||
"https://github.com/wTechArtist/ComfyUI_WWL_Florence2SAM2": [
|
"https://github.com/wTechArtist/ComfyUI_WWL_Florence2SAM2": [
|
||||||
[
|
[
|
||||||
"WWL_Florence2SAM2"
|
"VVL_Florence2SAM2",
|
||||||
|
"VVL_GroundingDinoSAM2",
|
||||||
|
"VVL_SAM2Loader"
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
"title_aux": "ComfyUI_WWL_Florence2SAM2"
|
"title_aux": "ComfyUI_WWL_Florence2SAM2"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/wTechArtist/ComfyUI_vvl_BBOX": [
|
||||||
|
[
|
||||||
|
"vvl_BBoxInput"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "ComfyUI_vvl_BBOX"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/walterFeng/ComfyUI-Image-Utils": [
|
"https://github.com/walterFeng/ComfyUI-Image-Utils": [
|
||||||
[
|
[
|
||||||
"Calculate Image Brightness",
|
"Calculate Image Brightness",
|
||||||
@@ -7529,12 +7718,16 @@
|
|||||||
"https://github.com/xl0/q_tools": [
|
"https://github.com/xl0/q_tools": [
|
||||||
[
|
[
|
||||||
"PreviewModelMetadata",
|
"PreviewModelMetadata",
|
||||||
|
"QConcatLatentBatch",
|
||||||
"QGaussianLatent",
|
"QGaussianLatent",
|
||||||
|
"QImageSizeSetter",
|
||||||
"QKSampler",
|
"QKSampler",
|
||||||
|
"QLatentToShape",
|
||||||
"QLinearScheduler",
|
"QLinearScheduler",
|
||||||
"QLoadLatent",
|
"QLoadLatent",
|
||||||
"QLoadLatentTimeline",
|
"QLoadLatentTimeline",
|
||||||
"QPreviewLatent",
|
"QPreviewLatent",
|
||||||
|
"QReshapeLatent",
|
||||||
"QSamplerCustom",
|
"QSamplerCustom",
|
||||||
"QSamplerEulerAncestral",
|
"QSamplerEulerAncestral",
|
||||||
"QUniformLatent"
|
"QUniformLatent"
|
||||||
@@ -7549,9 +7742,11 @@
|
|||||||
"BlendLatentsX",
|
"BlendLatentsX",
|
||||||
"ColorCorrectionX",
|
"ColorCorrectionX",
|
||||||
"ColorSpaceConversionX",
|
"ColorSpaceConversionX",
|
||||||
|
"ColorTransferNodeX",
|
||||||
"CommonSourcesX",
|
"CommonSourcesX",
|
||||||
"ConstantColorX",
|
"ConstantColorX",
|
||||||
"ConvexHullByMaskX",
|
"ConvexHullByMaskX",
|
||||||
|
"CropBorderX",
|
||||||
"DepthDisplaceX",
|
"DepthDisplaceX",
|
||||||
"EmptyLatentX",
|
"EmptyLatentX",
|
||||||
"ExpressionsX",
|
"ExpressionsX",
|
||||||
@@ -7567,12 +7762,16 @@
|
|||||||
"LoopCloseX",
|
"LoopCloseX",
|
||||||
"LoopOpenX",
|
"LoopOpenX",
|
||||||
"LoraBatchSamplerX",
|
"LoraBatchSamplerX",
|
||||||
|
"RegionTesterNodeX",
|
||||||
"RegionalPromptSamplerX",
|
"RegionalPromptSamplerX",
|
||||||
"RelightX",
|
"RelightX",
|
||||||
"RemoveBackgroundX",
|
"RemoveBackgroundX",
|
||||||
"SaveImageX",
|
"SaveImageX",
|
||||||
|
"SelectiveDepthLoraBlocksX",
|
||||||
"SimpleBlockerX",
|
"SimpleBlockerX",
|
||||||
"SplineImageMask",
|
"SplineImageMask",
|
||||||
|
"TextConcatX",
|
||||||
|
"TextX",
|
||||||
"WhiteBalanceX"
|
"WhiteBalanceX"
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
@@ -7658,6 +7857,7 @@
|
|||||||
"ImageLama",
|
"ImageLama",
|
||||||
"ImageToMasks",
|
"ImageToMasks",
|
||||||
"LAM.OpenPoseEditorPlus",
|
"LAM.OpenPoseEditorPlus",
|
||||||
|
"LamCommonHidden",
|
||||||
"LamCommonNames",
|
"LamCommonNames",
|
||||||
"LamCommonPrint",
|
"LamCommonPrint",
|
||||||
"LamCommonPrintNoOutput",
|
"LamCommonPrintNoOutput",
|
||||||
@@ -7666,7 +7866,9 @@
|
|||||||
"LamLoadImageBase64",
|
"LamLoadImageBase64",
|
||||||
"LamLoadPathImage",
|
"LamLoadPathImage",
|
||||||
"LamLoadVideo",
|
"LamLoadVideo",
|
||||||
|
"LamSamplerName",
|
||||||
"LamSaveOnly",
|
"LamSaveOnly",
|
||||||
|
"LamScheduler",
|
||||||
"LamSwitcherCase",
|
"LamSwitcherCase",
|
||||||
"LoadDirImgPaths",
|
"LoadDirImgPaths",
|
||||||
"LoadReplaceImage",
|
"LoadReplaceImage",
|
||||||
@@ -7746,6 +7948,15 @@
|
|||||||
"title_aux": "ComfyUI-StoryboardDistributor"
|
"title_aux": "ComfyUI-StoryboardDistributor"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"https://github.com/zhengxyz123/ComfyUI-CLIPSeg": [
|
||||||
|
[
|
||||||
|
"CLIPSegImage",
|
||||||
|
"CLIPSegText"
|
||||||
|
],
|
||||||
|
{
|
||||||
|
"title_aux": "zhengxyz123/ComfyUI-CLIPSeg [NAME CONFLICT]"
|
||||||
|
}
|
||||||
|
],
|
||||||
"https://github.com/zhongpei/Comfyui_image2prompt": [
|
"https://github.com/zhongpei/Comfyui_image2prompt": [
|
||||||
[
|
[
|
||||||
"CLIP AdvancedTextEncode|fofo",
|
"CLIP AdvancedTextEncode|fofo",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,36 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"author": "pomePLaszlo-collablyu",
|
||||||
|
"title": "comfyui_ejam [REMOVED]",
|
||||||
|
"reference": "https://github.com/PLaszlo-collab/comfyui_ejam",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/PLaszlo-collab/comfyui_ejam"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Ejam nodes for comfyui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "jonnydolake",
|
||||||
|
"title": "ComfyUI-AIR-Nodes [REMOVED]",
|
||||||
|
"reference": "https://github.com/jonnydolake/ComfyUI-AIR-Nodes",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/jonnydolake/ComfyUI-AIR-Nodes"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "NODES: String List To Prompt Schedule, Force Minimum Batch Size, Target Location (Crop), Target Location (Paste), Image Composite Chained, Match Image Count To Mask Count, Random Character Prompts, Parallax Test, Easy Parallax, Parallax GPU Test"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "solution9th",
|
||||||
|
"title": "Comfyui_mobilesam [REMOVED]",
|
||||||
|
"reference": "https://github.com/solution9th/Comfyui_mobilesam",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/solution9th/Comfyui_mobilesam"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "NODES: Mobile SAM Model Loader, Mobile SAM Detector, Mobile SAM Predictor"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "syaofox",
|
"author": "syaofox",
|
||||||
"title": "ComfyUI_fnodes [REMOVED]",
|
"title": "ComfyUI_fnodes [REMOVED]",
|
||||||
|
|||||||
@@ -10,6 +10,349 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"author": "Yuan-ManX",
|
||||||
|
"title": "ComfyUI-Bagel",
|
||||||
|
"reference": "https://github.com/Yuan-ManX/ComfyUI-Bagel",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/Yuan-ManX/ComfyUI-Bagel"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "ComfyUI-Bagel is now available in ComfyUI, BAGEL is an open‑source multimodal foundation model with 7B active parameters (14B total) trained on large‑scale interleaved multimodal data."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "TensorKaze",
|
||||||
|
"title": "ComfyUI-TkNodes",
|
||||||
|
"id": "ComfyUI-TkNodes",
|
||||||
|
"reference": "https://github.com/TensorKaze/ComfyUI-TkNodes",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/TensorKaze/ComfyUI-TkNodes"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Custom nodes for ComfyUI with advanced image scaling, latent manipulation, and Flux sampling"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "pureexe",
|
||||||
|
"title": "DiffusionLight-ComfyUI",
|
||||||
|
"reference": "https://github.com/pureexe/DiffusionLight-ComfyUI",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/pureexe/DiffusionLight-ComfyUI"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "DiffusionLight (Turbo) implemented in ComfyUI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "MrSamSeen",
|
||||||
|
"title": "ComfyUI_SSBeforeAfterNode",
|
||||||
|
"id": "ComfyUI_SSBeforeAfterNode",
|
||||||
|
"reference": "https://github.com/MrSamSeen/ComfyUI_SSBeforeAfterNode",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/MrSamSeen/ComfyUI_SSBeforeAfterNode"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Two powerful custom nodes for ComfyUI to create stunning before-and-after transition videos. These nodes are designed for visual comparisons, transformations, and creative effects, supporting both standard and depth map-based transitions."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "hmwl",
|
||||||
|
"title": "ComfyUI-TaskMonitor",
|
||||||
|
"reference": "https://github.com/hmwl/ComfyUI-TaskMonitor",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/hmwl/ComfyUI-TaskMonitor"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A powerful task monitoring extension for ComfyUI that provides real-time progress tracking, workflow statistics, and execution monitoring."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "karthikg-09",
|
||||||
|
"title": "ComfyUI-Vton-Mask",
|
||||||
|
"reference": "https://github.com/karthikg-09/ComfyUI-Vton-Mask",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/karthikg-09/ComfyUI-Vton-Mask"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A lightweight ComfyUI custom node for generating high-quality masks and pose detection for virtual try-on applications. This node extracts only the essential masking functionality from FitDiT without requiring heavy diffusion models."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "KAVVATARE",
|
||||||
|
"title": "RightEyeDisparity",
|
||||||
|
"reference": "https://github.com/KAVVATARE/ComfyUI_RightEyeDisparity",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/KAVVATARE/ComfyUI_RightEyeDisparity"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A simple ComfyUI node for generating right eye disparity for VR videos"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "jaimitoes",
|
||||||
|
"title": "ComfyUI_Wan2_1_lora_trainer",
|
||||||
|
"reference": "https://github.com/jaimitoes/ComfyUI_Wan2_1_lora_trainer",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/jaimitoes/ComfyUI_Wan2_1_lora_trainer"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "ComfyUI interface adaptation of the musubi-tunner library to train Wan 2.1 loras."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "angree",
|
||||||
|
"title": "ComfyUI-Q_GLB_Material_Modifier",
|
||||||
|
"reference": "https://github.com/angree/ComfyUI-Q_GLB_Material_Modifier",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/angree/ComfyUI-Q_GLB_Material_Modifier"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A ComfyUI custom node for enhancing GLB 3D models generated with Hunyuan 3D 2.0. This module helps solve the common 'plastic look' problem by adding realistic materials and smart emissive elements."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "R5-Revo",
|
||||||
|
"title": "Universal LLM Node for ComfyUI",
|
||||||
|
"reference": "https://github.com/R5-Revo/llm-node-comfyui",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/R5-Revo/llm-node-comfyui"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "UniversalLLMNode is a custom node for ComfyUI that provides a unified interface to use multiple major LLM APIs, including OpenAI, Anthropic (Claude), Google Gemini, Groq, and Mistral. It is ideal for tasks such as automatically generating high-quality SDXL prompts for image generation."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "ComfyAssets",
|
||||||
|
"title": "ComfyUI Prompt Manager",
|
||||||
|
"reference": "https://github.com/ComfyAssets/ComfyUI_PromptManager",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/ComfyAssets/ComfyUI_PromptManager"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A powerful ComfyUI custom node that extends the standard text encoder with persistent prompt storage, advanced search capabilities, and an automatic image gallery system using SQLite."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "silveroxides",
|
||||||
|
"title": "ComfyUI_EmbeddingToolkit",
|
||||||
|
"reference": "https://github.com/silveroxides/ComfyUI_EmbeddingToolkit",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/silveroxides/ComfyUI_EmbeddingToolkit"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Toolkit for creating embeddings for various models in ComfyUI."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "LevelPixel",
|
||||||
|
"title": "ComfyUI_LevelPixel_Advanced",
|
||||||
|
"id": "levelpixel_advanced",
|
||||||
|
"reference": "https://github.com/LevelPixel/ComfyUI-LevelPixel-Advanced",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/LevelPixel/ComfyUI-LevelPixel-Advanced"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Advanced nodes of the Level Pixel company. Includes convenient advanced nodes for working with LLM и VLM models (LLaVa) with GGUF format. Qwen2.5-VL and Qwen2.5 supported. Also included is a node for the RAM model. Nodes have the ability to automatically unload models from VRAM."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "SanDiegoDude",
|
||||||
|
"title": "ComfyUI-DeepStereo",
|
||||||
|
"reference": "https://github.com/SanDiegoDude/ComfyUI-DeepStereo",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/SanDiegoDude/ComfyUI-DeepStereo"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "ComfyUI nodes for DeepStereo, an auto-autostereogram generator"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "ptmaster",
|
||||||
|
"title": "ComfyUI-audio-speed",
|
||||||
|
"reference": "https://github.com/ptmaster/comfyui-audio-speed",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/ptmaster/comfyui-audio-speed"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "This node pack is designed to adjust audio playback speed within ComfyUI, particularly to sync audio with models like FantasyTalking (WAN) that require specific frame rates. It can also be used for general-purpose audio speed control."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "ShmuelRonen",
|
||||||
|
"title": "ComfyUI-Gemini_TTS",
|
||||||
|
"reference": "https://github.com/ShmuelRonen/ComfyUI-Gemini_TTS",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/ShmuelRonen/ComfyUI-Gemini_TTS"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A powerful ComfyUI custom node that brings Google's Gemini TTS capabilities directly to your workflow. Generate high-quality speech with 30+ voices supporting both free and paid tiers."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "1038lab",
|
||||||
|
"title": "ComfyUI-JoyCaption",
|
||||||
|
"reference": "https://github.com/1038lab/ComfyUI-JoyCaption",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/1038lab/ComfyUI-JoyCaption"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "ComfyUI custom node powered by LLaVA VLM for advanced image captioning with customizable styles and memory-efficient inference."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "thezveroboy",
|
||||||
|
"title": "ComfyUI-LUT",
|
||||||
|
"reference": "https://github.com/thezveroboy/ComfyUI-lut",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/thezveroboy/ComfyUI-lut"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Custom nodes for ComfyUI for simple LUT file extraction from any image."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "TFL-TFL",
|
||||||
|
"title": "ComfyUI_Text_Translation",
|
||||||
|
"reference": "https://github.com/TFL-TFL/ComfyUI_Text_Translation",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/TFL-TFL/ComfyUI_Text_Translation"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Text translation node for ComfyUI: No need to apply for a translation API key, just use it. Currently supports more than thirty translation platforms."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "shinich39",
|
||||||
|
"title": "comfyui-break-workflow",
|
||||||
|
"reference": "https://github.com/shinich39/comfyui-break-workflow",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/shinich39/comfyui-break-workflow"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Break the execution, save the incompleted image then continue later."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Charonartist",
|
||||||
|
"title": "ComfyUI-EagleExporter",
|
||||||
|
"reference": "https://github.com/Charonartist/ComfyUI-EagleExporter",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/Charonartist/ComfyUI-EagleExporter"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "This is an extension that automatically saves video files generated with ComfyUI's 'video combine' extension to the Eagle library."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Charonartist",
|
||||||
|
"title": "Comfyui_gemini_tts_node",
|
||||||
|
"reference": "https://github.com/Charonartist/Comfyui_gemini_tts_node",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/Charonartist/Comfyui_gemini_tts_node"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "This custom node is a ComfyUI node for generating speech from text using the Gemini 2.5 Flash Preview TTS API."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "babe-and-spencer-enterprises",
|
||||||
|
"title": "ComfyUI Upload to BASE Node",
|
||||||
|
"reference": "https://github.com/babe-and-spencer-enterprises/base-comfyui-node",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/babe-and-spencer-enterprises/base-comfyui-node"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A custom ComfyUI node that lets you upload generated images directly to your [a/BASE](https://getbase.app/) account — no manual downloads or re-uploads needed."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "wildminder",
|
||||||
|
"title": "ComfyUI-KEEP",
|
||||||
|
"reference": "https://github.com/wildminder/ComfyUI-KEEP",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/wildminder/ComfyUI-KEEP"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "ComfyUI-KEEP: Kalman-Inspired Feature Propagation for Video Face Super-Resolution in ComfyUI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "mw",
|
||||||
|
"title": "Comfyui_HeyGem",
|
||||||
|
"reference": "https://github.com/billwuhao/Comfyui_HeyGem",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/billwuhao/Comfyui_HeyGem"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "HeyGem AI avatar."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Limbicnation",
|
||||||
|
"title": "Transparency Background Remover",
|
||||||
|
"reference": "https://github.com/Limbicnation/ComfyUI-TransparencyBackgroundRemover",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/Limbicnation/ComfyUI-TransparencyBackgroundRemover"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "Automatic background removal and transparency generation for ComfyUI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "kevin314",
|
||||||
|
"title": "ComfyUI-FastVideo",
|
||||||
|
"reference": "https://github.com/kevin314/ComfyUI-FastVideo",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/kevin314/ComfyUI-FastVideo"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A custom node suite for ComfyUI that provides accelerated video generation using [a/FastVideo](https://github.com/hao-ai-labs/FastVideo). See the [a/blog post](https://hao-ai-lab.github.io/blogs/fastvideo/) about FastVideo V1 to learn more."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "AEmotionStudio",
|
||||||
|
"title": "ComfyUI-ShaderNoiseKSampler",
|
||||||
|
"reference": "https://github.com/AEmotionStudio/ComfyUI-ShaderNoiseKSampler",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/AEmotionStudio/ComfyUI-ShaderNoiseKSampler"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "ComfyUI-ShaderNoiseKSampler is an advanced custom KSampler node that replaces standard noise generation with a multi-stage shader-based system. Unlike traditional sampling that teleports randomly between different seeds, this tool provides a structured vehicle for exploring the neighborhood around a chosen seed, using mathematical patterns to navigate along coherent paths through latent space."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "cloudkoala",
|
||||||
|
"title": "comfyui-koala",
|
||||||
|
"reference": "https://github.com/cloudkoala/comfyui-koala",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/cloudkoala/comfyui-koala"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "A collection of custom nodes for ComfyUI focused on aspect ratio management and other utilities."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "lepiai",
|
||||||
|
"title": "ComfyUI-Minitools",
|
||||||
|
"reference": "https://github.com/lepiai/ComfyUI-Minitools",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/lepiai/ComfyUI-Minitools"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "ComfyUI Mini Toolkit – Helps reduce node redundancy. Let’s see if there’s time to keep it updated regularly."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Yuan-ManX",
|
||||||
|
"title": "ComfyUI-AniSora",
|
||||||
|
"reference": "https://github.com/Yuan-ManX/ComfyUI-AniSora",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/Yuan-ManX/ComfyUI-AniSora"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "ComfyUI-AniSora is now available in ComfyUI, Index-AniSora is the most powerful open-source animated video generation model. It enables one-click creation of video shots across diverse anime styles including series episodes, Chinese original animations, manga adaptations, VTuber content, anime PVs, mad-style parodies(鬼畜动画), and more!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "smthemex",
|
||||||
|
"title": "ComfyUI_VisualCloze",
|
||||||
|
"reference": "https://github.com/smthemex/ComfyUI_VisualCloze",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/smthemex/ComfyUI_VisualCloze"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "VisualCloze: A Universal Image Generation Framework via Visual In-Context Learning,you can use it in ComfyUI"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "lrzjason",
|
||||||
|
"title": "ComfyUI Watermark Detection Node",
|
||||||
|
"reference": "https://github.com/lrzjason/ComfyUI-Watermark-Detection",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/lrzjason/ComfyUI-Watermark-Detection"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "This custom node for ComfyUI provides watermark detection capabilities using a YOLO model trained by [a/fancyfeast](https://huggingface.co/fancyfeast), the creator of JoyCaption. The model is originally hosted at [a/Hugging Face Space](https://huggingface.co/spaces/fancyfeast/joycaption-watermark-detection)."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "craig-tanaka",
|
||||||
|
"title": "ComfyUI Anime Segmentation Nodes v1.1.0",
|
||||||
|
"reference": "https://github.com/craig-tanaka/comfyui_animeseg",
|
||||||
|
"files": [
|
||||||
|
"https://github.com/craig-tanaka/comfyui_animeseg"
|
||||||
|
],
|
||||||
|
"install_type": "git-clone",
|
||||||
|
"description": "This is a set of custom nodes for ComfyUI that provide anime-style image segmentation using efficient pre-trained models."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"author": "lum3on",
|
"author": "lum3on",
|
||||||
"title": "ComfyUI Model Quantizer",
|
"title": "ComfyUI Model Quantizer",
|
||||||
@@ -356,403 +699,6 @@
|
|||||||
],
|
],
|
||||||
"install_type": "git-clone",
|
"install_type": "git-clone",
|
||||||
"description": "Provide powerful frontend and backend integration node packages for ComfyUI - this is an exceptionally robust integration extension."
|
"description": "Provide powerful frontend and backend integration node packages for ComfyUI - this is an exceptionally robust integration extension."
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "Dontdrunk",
|
|
||||||
"title": "ComfyUI-DD-Translation",
|
|
||||||
"id": "comfyui-dd-translation",
|
|
||||||
"reference": "https://github.com/Dontdrunk/ComfyUI-DD-Translation",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/Dontdrunk/ComfyUI-DD-Translation"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "A plugin offering supplementary Chinese translations for ComfyUI custom nodes."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "thezveroboy",
|
|
||||||
"title": "ComfyUI_ACE-Step-zveroboy",
|
|
||||||
"reference": "https://github.com/thezveroboy/ComfyUI_ACE-Step-zveroboy",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/thezveroboy/ComfyUI_ACE-Step-zveroboy"
|
|
||||||
],
|
|
||||||
"description": "I took the original source code from the repository [a/ComfyUI_ACE-Step](https://github.com/billwuhao/ComfyUI_ACE-Step) and modified it to make the model loading explicit instead of hidden.",
|
|
||||||
"install_type": "git-clone"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "Makki_Shizu",
|
|
||||||
"title": "ComfyUI-Qwen2_5-VL",
|
|
||||||
"reference": "https://github.com/MakkiShizu/ComfyUI-Qwen2_5-VL",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/MakkiShizu/ComfyUI-Qwen2_5-VL"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Qwen2.5-VL in ComfyUI"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "GroxicTinch",
|
|
||||||
"title": "EasyUI",
|
|
||||||
"reference": "https://github.com/GroxicTinch/EasyUI-ComfyUI",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/GroxicTinch/EasyUI-ComfyUI"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Allows making a mirror of options that are on a node, for use creating your own UI"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "lerignoux",
|
|
||||||
"title": "ComfyUI-PechaKucha",
|
|
||||||
"reference": "https://github.com/lerignoux/ComfyUI-PechaKucha",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/lerignoux/ComfyUI-PechaKucha"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Comfy UI nodes to generate pecha kucha presentations"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "phazei",
|
|
||||||
"title": "Prompt Stash",
|
|
||||||
"id": "ComfyUI-Prompt-Stash",
|
|
||||||
"reference": "https://github.com/phazei/ComfyUI-Prompt-Stash",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/phazei/ComfyUI-Prompt-Stash"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Prompt Stash is a simple plugin for ComfyUI that lets you save your prompts and organize them into multiple lists. It also features a pass-through functionality, so you can hook it up to an LLM node (or any text outputting node) and capture its outputs directly."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "HJH-AILab",
|
|
||||||
"title": "ComfyUI_CosyVoice2",
|
|
||||||
"reference": "https://github.com/HJH-AILab/ComfyUI_CosyVoice2",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/HJH-AILab/ComfyUI_CosyVoice2"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "A wrapper of [a/CosyVoice2](https://github.com/FunAudioLLM/CosyVoice/)'s ComfyUI custom_nodes"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "Ky11le",
|
|
||||||
"title": "draw_tools",
|
|
||||||
"reference": "https://github.com/Ky11le/draw_tools",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/Ky11le/draw_tools"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "A ComfyUI custom node for tiling images horizontally with configurable spacing"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "otacoo",
|
|
||||||
"title": "comfyui-holdup",
|
|
||||||
"reference": "https://github.com/usrname0/comfyui-holdup",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/usrname0/comfyui-holdup"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "A ComfyUI node that waits for a GPU temp and/or a number of seconds."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "vladpro3",
|
|
||||||
"title": "ComfyUI_BishaNodes",
|
|
||||||
"reference": "https://github.com/vladpro3/ComfyUI_BishaNodes",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/vladpro3/ComfyUI_BishaNodes"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Custom nodes for ComfyUI to generate images in multiple resolutions (including ultra-wide formats)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "otacoo",
|
|
||||||
"title": "Metadata-Extractor",
|
|
||||||
"reference": "https://github.com/otacoo/comfyui_otacoo",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/otacoo/comfyui_otacoo"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Extract generation info from PNG and JPEG images, supports both A1111 and (some) ComfyUI metadata"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "newtextdoc1111",
|
|
||||||
"title": "ComfyUI-Autocomplete-Plus",
|
|
||||||
"reference": "https://github.com/newtextdoc1111/ComfyUI-Autocomplete-Plus",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/newtextdoc1111/ComfyUI-Autocomplete-Plus"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Custom node to add autocomplete functionality [ComfyUI-Autocomplete-Plus](https://github.com/newtextdoc1111/ComfyUI-Autocomplete-Plus)."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "bollerdominik",
|
|
||||||
"title": "ComfyUI-load-lora-from-url",
|
|
||||||
"reference": "https://github.com/bollerdominik/ComfyUI-load-lora-from-url",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/bollerdominik/ComfyUI-load-lora-from-url"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "A simple node to load image from local path or http url."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "azure-dragon-ai",
|
|
||||||
"title": "ComfyUI-HPSv2-Nodes",
|
|
||||||
"reference": "https://github.com/azure-dragon-ai/ComfyUI-HPSv2-Nodes",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/azure-dragon-ai/ComfyUI-HPSv2-Nodes"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "ComfyUI Nodes for HPSv2, Human Preference Score v2: A Solid Benchmark for Evaluating Human Preferences of Text-to-Image Synthesis"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "ShmuelRonen",
|
|
||||||
"title": "ComfyUI-Audio_Quality_Enhancer",
|
|
||||||
"reference": "https://github.com/ShmuelRonen/ComfyUI-Audio_Quality_Enhancer",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/ShmuelRonen/ComfyUI-Audio_Quality_Enhancer"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "An extension that's adds advanced audio processing capabilities to ComfyUI with professional-grade audio effects and AI-powered audio enhancement."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "wings6407",
|
|
||||||
"title": "ComfyUI_HBH-image_overlay",
|
|
||||||
"reference": "https://github.com/wings6407/ComfyUI_HBH-image_overlay",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/wings6407/ComfyUI_HBH-image_overlay"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Use the point editor to perform image composition editing."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "monkeyWie",
|
|
||||||
"title": "ComfyUI-FormInput",
|
|
||||||
"reference": "https://github.com/monkeyWie/ComfyUI-FormInput",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/monkeyWie/ComfyUI-FormInput"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "This custom node for ComfyUI provides a set of input elements to create forms or interact with your workflows."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "XchanBik",
|
|
||||||
"title": "ComfyUI_SimpleBridgeNode",
|
|
||||||
"reference": "https://github.com/XchanBik/ComfyUI_SimpleBridgeNode",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/XchanBik/ComfyUI_SimpleBridgeNode"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "This node can store a route with a chosen ID then load it anywhere in the workflow. Goal it to make linking less messy in my taste."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "Sinphaltimus",
|
|
||||||
"title": "comfyui_fedcoms_node_pack",
|
|
||||||
"reference": "https://github.com/Sinphaltimus/comfyui_fedcoms_node_pack",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/Sinphaltimus/comfyui_fedcoms_node_pack"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Several nodes that attempt to extract metadata and raw text information from Gen AI models."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "marklieberman",
|
|
||||||
"title": "ComfyUI-Liebs-Title",
|
|
||||||
"reference": "https://github.com/marklieberman/ComfyUI-Liebs-Title",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/marklieberman/ComfyUI-Liebs-Title"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "An extension to modify the browser tab title when running ComfyUI workflows."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "neggo",
|
|
||||||
"title": "comfyui-sambanova",
|
|
||||||
"reference": "https://github.com/neggo/comfyui-sambanova",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/neggo/comfyui-sambanova"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "This node pack provides a Python node that uses the SambaNova API to send prompts to a chat AI model (e.g., DeepSeek-V3-0324) and retrieve responses, intended for integration into node-based workflows like ComfyUI."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "theshubzworld",
|
|
||||||
"title": "ComfyUI-FaceCalloutNode",
|
|
||||||
"reference": "https://github.com/theshubzworld/ComfyUI-FaceCalloutNode",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/theshubzworld/ComfyUI-FaceCalloutNode"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "A collection of custom nodes for ComfyUI that provide advanced face callout, annotation, and compositing effects using OpenCV and PIL. These nodes are designed for image processing workflows that require face detection, annotation, and creative compositing."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "yichengup",
|
|
||||||
"title": "ComfyUI-LinearTransition",
|
|
||||||
"reference": "https://github.com/yichengup/ComfyUI-LinearTransition",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/yichengup/ComfyUI-LinearTransition"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "This is a custom node designed for ComfyUI to create transition effects between two images and generate a sequence of video frames."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "northumber",
|
|
||||||
"title": "ComfyUI-northTools",
|
|
||||||
"reference": "https://github.com/northumber/ComfyUI-northTools",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/northumber/ComfyUI-northTools"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Collection of nodes for ComfyUI for automation"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "Jacky-MYQ",
|
|
||||||
"title": "comfyui-DataCleaning",
|
|
||||||
"reference": "https://github.com/Jacky-MYQ/comfyui-DataCleaning",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/Jacky-MYQ/comfyui-DataCleaning"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Image cropping and Image resizing"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "lihaoyun6",
|
|
||||||
"title": "ComfyUI-CSV-Random-Picker",
|
|
||||||
"reference": "https://github.com/lihaoyun6/ComfyUI-CSV-Random-Picker",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/lihaoyun6/ComfyUI-CSV-Random-Picker"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "String random picker for ComfyUI"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "krmahil",
|
|
||||||
"title": "Hollow Preserve",
|
|
||||||
"reference": "https://github.com/krmahil/comfyui-hollow-preserve",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/krmahil/comfyui-hollow-preserve"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "A ComfyUI node that breaks closed loops in masks to prevent inpainting models from modifying enclosed regions"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "Yuan-ManX",
|
|
||||||
"title": "ComfyUI-Multiverse",
|
|
||||||
"reference": "https://github.com/Yuan-ManX/ComfyUI-Multiverse",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/Yuan-ManX/ComfyUI-Multiverse"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Make Multiverse avialbe in ComfyUI.\nMultiverse: The First AI Multiplayer World Model. Two human players driving cars in Multiverse."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "SparknightLLC",
|
|
||||||
"title": "ComfyUI-ImageAutosize",
|
|
||||||
"reference": "https://github.com/SparknightLLC/ComfyUI-ImageAutosize",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/SparknightLLC/ComfyUI-ImageAutosize"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "A node for ComfyUI that provides a convenient way of resizing or cropping an image for diffusion tasks."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "tavyra",
|
|
||||||
"title": "ComfyUI_Curves",
|
|
||||||
"reference": "https://github.com/tavyra/ComfyUI_Curves",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/tavyra/ComfyUI_Curves"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Generate or draw FLOAT arrays within ComfyUI"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "SanDiegoDude",
|
|
||||||
"title": "ComfyUI-SaveAudioMP3",
|
|
||||||
"reference": "https://github.com/SanDiegoDude/ComfyUI-SaveAudioMP3",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/SanDiegoDude/ComfyUI-SaveAudioMP3"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "quick Comfy Node to convert input waveform audio to MP3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "hayd-zju",
|
|
||||||
"title": "ICEdit-ComfyUI-official",
|
|
||||||
"reference": "https://github.com/hayd-zju/ICEdit-ComfyUI-official",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/hayd-zju/ICEdit-ComfyUI-official"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "This node pack provides the official ComfyUI workflow for ICEdit."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "Yuan-ManX",
|
|
||||||
"title": "ComfyUI-Muyan-TTS",
|
|
||||||
"reference": "https://github.com/Yuan-ManX/ComfyUI-Muyan-TTS",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/Yuan-ManX/ComfyUI-Muyan-TTS"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Make Muyan-TTS avialbe in ComfyUI."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "fpgaminer",
|
|
||||||
"title": "JoyCaption Nodes",
|
|
||||||
"id": "comfyui-joycaption",
|
|
||||||
"reference": "https://github.com/fpgaminer/joycaption_comfyui",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/fpgaminer/joycaption_comfyui"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Nodes for running the JoyCaption image captioner VLM."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "Goshe-nite",
|
|
||||||
"title": "GPS' Supplements for ComfyUI",
|
|
||||||
"id": "GPSupps",
|
|
||||||
"reference": "https://github.com/Goshe-nite/comfyui-gps-supplements",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/Goshe-nite/comfyui-gps-supplements"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Nodes to make ComfyUI-Image-Saver and rgthree-comfy more compatible. Allowing Power Lora Loader node to be used with Image Saver node. Also adding nodes to extract Image Saver compatible strings to simplify workflows."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "AIWarper",
|
|
||||||
"title": "NormalCrafterWrapper",
|
|
||||||
"id": "normal-crafter-wrapper",
|
|
||||||
"reference": "https://github.com/AIWarper/ComfyUI-NormalCrafterWrapper",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/AIWarper/ComfyUI-NormalCrafterWrapper"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "ComfyUI diffusers wrapper nodes for [a/NormalCrafter](https://github.com/Binyr/NormalCrafter)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "pixible",
|
|
||||||
"title": "comfyui-customselector",
|
|
||||||
"reference": "https://github.com/gasparuff/CustomSelector",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/gasparuff/CustomSelector"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Helps deciding different settings depending on the input string"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "1hew",
|
|
||||||
"title": "ComfyUI 1hewNodes",
|
|
||||||
"id": "ComfyUI-1hewNodes",
|
|
||||||
"reference": "https://github.com/1hew/ComfyUI-1hewNodes",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/1hew/ComfyUI-1hewNodes"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "This is a custom node collection for ComfyUI that provides some utility nodes."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"author": "cyberhirsch",
|
|
||||||
"title": "Seb Nodes",
|
|
||||||
"id": "seb_nodes",
|
|
||||||
"reference": "https://github.com/cyberhirsch/seb_nodes",
|
|
||||||
"files": [
|
|
||||||
"https://github.com/cyberhirsch/seb_nodes"
|
|
||||||
],
|
|
||||||
"install_type": "git-clone",
|
|
||||||
"description": "Save image node with dynamic paths and an 'Open Folder' button."
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
846
openapi.yaml
Normal file
846
openapi.yaml
Normal file
@@ -0,0 +1,846 @@
|
|||||||
|
openapi: 3.1.0
|
||||||
|
info:
|
||||||
|
title: ComfyUI-Manager API
|
||||||
|
description: |
|
||||||
|
API for ComfyUI-Manager, a comprehensive management tool for ComfyUI custom nodes, models, and components.
|
||||||
|
This API enables programmatic access to node management, model downloading, snapshot operations,
|
||||||
|
and overall system configuration.
|
||||||
|
version: "3.32.3"
|
||||||
|
contact:
|
||||||
|
name: ComfyUI-Manager Maintainers
|
||||||
|
servers:
|
||||||
|
- url: '/'
|
||||||
|
description: Default ComfyUI server
|
||||||
|
|
||||||
|
# Common API components
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
Error:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
error:
|
||||||
|
type: string
|
||||||
|
description: Error message
|
||||||
|
|
||||||
|
NodePackageMetadata:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
|
description: Display name of the node package
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: Repository/package name
|
||||||
|
files:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
description: Source URLs for the package
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
description: Description of the node package functionality
|
||||||
|
install_type:
|
||||||
|
type: string
|
||||||
|
enum: [git, copy, pip]
|
||||||
|
description: Installation method
|
||||||
|
version:
|
||||||
|
type: string
|
||||||
|
description: Version identifier
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
description: Unique identifier for the node package
|
||||||
|
ui_id:
|
||||||
|
type: string
|
||||||
|
description: ID for UI reference
|
||||||
|
channel:
|
||||||
|
type: string
|
||||||
|
description: Source channel
|
||||||
|
mode:
|
||||||
|
type: string
|
||||||
|
description: Source mode
|
||||||
|
|
||||||
|
ModelMetadata:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: Name of the model
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
description: Type of model
|
||||||
|
base:
|
||||||
|
type: string
|
||||||
|
description: Base model type
|
||||||
|
save_path:
|
||||||
|
type: string
|
||||||
|
description: Path for saving the model
|
||||||
|
url:
|
||||||
|
type: string
|
||||||
|
description: Download URL
|
||||||
|
filename:
|
||||||
|
type: string
|
||||||
|
description: Target filename
|
||||||
|
ui_id:
|
||||||
|
type: string
|
||||||
|
description: ID for UI reference
|
||||||
|
|
||||||
|
SnapshotItem:
|
||||||
|
type: string
|
||||||
|
description: Name of the snapshot
|
||||||
|
|
||||||
|
QueueStatus:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
total_count:
|
||||||
|
type: integer
|
||||||
|
description: Total number of tasks
|
||||||
|
done_count:
|
||||||
|
type: integer
|
||||||
|
description: Number of completed tasks
|
||||||
|
in_progress_count:
|
||||||
|
type: integer
|
||||||
|
description: Number of tasks in progress
|
||||||
|
is_processing:
|
||||||
|
type: boolean
|
||||||
|
description: Whether the queue is currently processing
|
||||||
|
|
||||||
|
securitySchemes:
|
||||||
|
securityLevel:
|
||||||
|
type: apiKey
|
||||||
|
in: header
|
||||||
|
name: Security-Level
|
||||||
|
description: Security level for sensitive operations
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
modeParam:
|
||||||
|
name: mode
|
||||||
|
in: query
|
||||||
|
description: Source mode (e.g., "local", "remote")
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
enum: [local, remote, default]
|
||||||
|
|
||||||
|
targetParam:
|
||||||
|
name: target
|
||||||
|
in: query
|
||||||
|
description: Target identifier
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
valueParam:
|
||||||
|
name: value
|
||||||
|
in: query
|
||||||
|
description: New value to set
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
# API Paths
|
||||||
|
paths:
|
||||||
|
# Custom Nodes Endpoints
|
||||||
|
/customnode/getmappings:
|
||||||
|
get:
|
||||||
|
summary: Get node-to-package mappings
|
||||||
|
description: Provides unified mapping between nodes and node packages
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/modeParam'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: array
|
||||||
|
description: Mapping of node packages to node classes
|
||||||
|
|
||||||
|
/customnode/fetch_updates:
|
||||||
|
get:
|
||||||
|
summary: Check for updates
|
||||||
|
description: Fetches updates for custom nodes
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/modeParam'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: No updates available
|
||||||
|
'201':
|
||||||
|
description: Updates found
|
||||||
|
'400':
|
||||||
|
description: Error occurred
|
||||||
|
|
||||||
|
/customnode/installed:
|
||||||
|
get:
|
||||||
|
summary: Get installed custom nodes
|
||||||
|
description: Returns a list of installed node packages
|
||||||
|
parameters:
|
||||||
|
- name: mode
|
||||||
|
in: query
|
||||||
|
description: Lists mode, default or imported
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
enum: [default, imported]
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
$ref: '#/components/schemas/NodePackageMetadata'
|
||||||
|
|
||||||
|
/customnode/getlist:
|
||||||
|
get:
|
||||||
|
summary: Get custom node list
|
||||||
|
description: Provides a list of available custom nodes
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/modeParam'
|
||||||
|
- name: skip_update
|
||||||
|
in: query
|
||||||
|
description: Skip update check
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
channel:
|
||||||
|
type: string
|
||||||
|
node_packs:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
$ref: '#/components/schemas/NodePackageMetadata'
|
||||||
|
|
||||||
|
/customnode/alternatives:
|
||||||
|
get:
|
||||||
|
summary: Get alternative node options
|
||||||
|
description: Provides alternatives for nodes
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/modeParam'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: object
|
||||||
|
|
||||||
|
/customnode/versions/{node_name}:
|
||||||
|
get:
|
||||||
|
summary: Get available versions for a node
|
||||||
|
description: Lists all available versions for a specific node
|
||||||
|
parameters:
|
||||||
|
- name: node_name
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
version:
|
||||||
|
type: string
|
||||||
|
'400':
|
||||||
|
description: Node not found
|
||||||
|
|
||||||
|
/customnode/disabled_versions/{node_name}:
|
||||||
|
get:
|
||||||
|
summary: Get disabled versions for a node
|
||||||
|
description: Lists all disabled versions for a specific node
|
||||||
|
parameters:
|
||||||
|
- name: node_name
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
version:
|
||||||
|
type: string
|
||||||
|
'400':
|
||||||
|
description: Node not found
|
||||||
|
|
||||||
|
/customnode/import_fail_info:
|
||||||
|
post:
|
||||||
|
summary: Get import failure information
|
||||||
|
description: Returns information about why a node failed to import
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
cnr_id:
|
||||||
|
type: string
|
||||||
|
url:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
'400':
|
||||||
|
description: No information available
|
||||||
|
|
||||||
|
/customnode/install/git_url:
|
||||||
|
post:
|
||||||
|
summary: Install custom node via Git URL
|
||||||
|
description: Installs a custom node from a Git repository URL
|
||||||
|
security:
|
||||||
|
- securityLevel: []
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
text/plain:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Installation successful or already installed
|
||||||
|
'400':
|
||||||
|
description: Installation failed
|
||||||
|
'403':
|
||||||
|
description: Security policy violation
|
||||||
|
|
||||||
|
/customnode/install/pip:
|
||||||
|
post:
|
||||||
|
summary: Install custom node dependencies via pip
|
||||||
|
description: Installs Python package dependencies for custom nodes
|
||||||
|
security:
|
||||||
|
- securityLevel: []
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
text/plain:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Installation successful
|
||||||
|
'403':
|
||||||
|
description: Security policy violation
|
||||||
|
|
||||||
|
# Model Management Endpoints
|
||||||
|
/externalmodel/getlist:
|
||||||
|
get:
|
||||||
|
summary: Get external model list
|
||||||
|
description: Provides a list of available external models
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/modeParam'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
models:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/ModelMetadata'
|
||||||
|
|
||||||
|
# Queue Management Endpoints
|
||||||
|
/manager/queue/update_all:
|
||||||
|
get:
|
||||||
|
summary: Update all custom nodes
|
||||||
|
description: Queues update operations for all installed custom nodes
|
||||||
|
security:
|
||||||
|
- securityLevel: []
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/modeParam'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Update queued successfully
|
||||||
|
'401':
|
||||||
|
description: Processing already in progress
|
||||||
|
'403':
|
||||||
|
description: Security policy violation
|
||||||
|
|
||||||
|
/manager/queue/reset:
|
||||||
|
get:
|
||||||
|
summary: Reset queue
|
||||||
|
description: Resets the operation queue
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Queue reset successfully
|
||||||
|
|
||||||
|
/manager/queue/status:
|
||||||
|
get:
|
||||||
|
summary: Get queue status
|
||||||
|
description: Returns the current status of the operation queue
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/QueueStatus'
|
||||||
|
|
||||||
|
/manager/queue/install:
|
||||||
|
post:
|
||||||
|
summary: Install custom node
|
||||||
|
description: Queues installation of a custom node
|
||||||
|
security:
|
||||||
|
- securityLevel: []
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/NodePackageMetadata'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Installation queued successfully
|
||||||
|
'403':
|
||||||
|
description: Security policy violation
|
||||||
|
'404':
|
||||||
|
description: Target node not found or security issue
|
||||||
|
|
||||||
|
/manager/queue/start:
|
||||||
|
get:
|
||||||
|
summary: Start queue processing
|
||||||
|
description: Starts processing the operation queue
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Processing started
|
||||||
|
'201':
|
||||||
|
description: Processing already in progress
|
||||||
|
|
||||||
|
/manager/queue/fix:
|
||||||
|
post:
|
||||||
|
summary: Fix custom node
|
||||||
|
description: Attempts to fix a broken custom node installation
|
||||||
|
security:
|
||||||
|
- securityLevel: []
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/NodePackageMetadata'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Fix operation queued successfully
|
||||||
|
'403':
|
||||||
|
description: Security policy violation
|
||||||
|
|
||||||
|
/manager/queue/reinstall:
|
||||||
|
post:
|
||||||
|
summary: Reinstall custom node
|
||||||
|
description: Uninstalls and then reinstalls a custom node
|
||||||
|
security:
|
||||||
|
- securityLevel: []
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/NodePackageMetadata'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Reinstall operation queued successfully
|
||||||
|
'403':
|
||||||
|
description: Security policy violation
|
||||||
|
|
||||||
|
/manager/queue/uninstall:
|
||||||
|
post:
|
||||||
|
summary: Uninstall custom node
|
||||||
|
description: Queues uninstallation of a custom node
|
||||||
|
security:
|
||||||
|
- securityLevel: []
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/NodePackageMetadata'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Uninstallation queued successfully
|
||||||
|
'403':
|
||||||
|
description: Security policy violation
|
||||||
|
|
||||||
|
/manager/queue/update:
|
||||||
|
post:
|
||||||
|
summary: Update custom node
|
||||||
|
description: Queues update of a custom node
|
||||||
|
security:
|
||||||
|
- securityLevel: []
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/NodePackageMetadata'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Update queued successfully
|
||||||
|
'403':
|
||||||
|
description: Security policy violation
|
||||||
|
|
||||||
|
/manager/queue/disable:
|
||||||
|
post:
|
||||||
|
summary: Disable custom node
|
||||||
|
description: Disables a custom node without uninstalling it
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/NodePackageMetadata'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Disable operation queued successfully
|
||||||
|
|
||||||
|
/manager/queue/update_comfyui:
|
||||||
|
get:
|
||||||
|
summary: Update ComfyUI
|
||||||
|
description: Queues an update operation for ComfyUI itself
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Update queued successfully
|
||||||
|
|
||||||
|
/manager/queue/install_model:
|
||||||
|
post:
|
||||||
|
summary: Install model
|
||||||
|
description: Queues installation of a model
|
||||||
|
security:
|
||||||
|
- securityLevel: []
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ModelMetadata'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Installation queued successfully
|
||||||
|
'400':
|
||||||
|
description: Invalid model request
|
||||||
|
'403':
|
||||||
|
description: Security policy violation
|
||||||
|
|
||||||
|
# Snapshot Management Endpoints
|
||||||
|
/snapshot/getlist:
|
||||||
|
get:
|
||||||
|
summary: Get snapshot list
|
||||||
|
description: Returns a list of available snapshots
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
items:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/SnapshotItem'
|
||||||
|
|
||||||
|
/snapshot/remove:
|
||||||
|
get:
|
||||||
|
summary: Remove snapshot
|
||||||
|
description: Removes a specified snapshot
|
||||||
|
security:
|
||||||
|
- securityLevel: []
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/targetParam'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Snapshot removed successfully
|
||||||
|
'400':
|
||||||
|
description: Error removing snapshot
|
||||||
|
'403':
|
||||||
|
description: Security policy violation
|
||||||
|
|
||||||
|
/snapshot/restore:
|
||||||
|
get:
|
||||||
|
summary: Restore snapshot
|
||||||
|
description: Restores a specified snapshot
|
||||||
|
security:
|
||||||
|
- securityLevel: []
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/targetParam'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Snapshot restoration scheduled
|
||||||
|
'400':
|
||||||
|
description: Error restoring snapshot
|
||||||
|
'403':
|
||||||
|
description: Security policy violation
|
||||||
|
|
||||||
|
/snapshot/get_current:
|
||||||
|
get:
|
||||||
|
summary: Get current snapshot
|
||||||
|
description: Returns the current system state as a snapshot
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
'400':
|
||||||
|
description: Error creating snapshot
|
||||||
|
|
||||||
|
/snapshot/save:
|
||||||
|
get:
|
||||||
|
summary: Save snapshot
|
||||||
|
description: Saves the current system state as a new snapshot
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Snapshot saved successfully
|
||||||
|
'400':
|
||||||
|
description: Error saving snapshot
|
||||||
|
|
||||||
|
# ComfyUI Management Endpoints
|
||||||
|
/comfyui_manager/comfyui_versions:
|
||||||
|
get:
|
||||||
|
summary: Get ComfyUI versions
|
||||||
|
description: Returns available and current ComfyUI versions
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
versions:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
current:
|
||||||
|
type: string
|
||||||
|
'400':
|
||||||
|
description: Error retrieving versions
|
||||||
|
|
||||||
|
/comfyui_manager/comfyui_switch_version:
|
||||||
|
get:
|
||||||
|
summary: Switch ComfyUI version
|
||||||
|
description: Switches to a specified ComfyUI version
|
||||||
|
parameters:
|
||||||
|
- name: ver
|
||||||
|
in: query
|
||||||
|
description: Target version
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Version switch successful
|
||||||
|
'400':
|
||||||
|
description: Error switching version
|
||||||
|
|
||||||
|
/manager/reboot:
|
||||||
|
get:
|
||||||
|
summary: Reboot ComfyUI
|
||||||
|
description: Restarts the ComfyUI server
|
||||||
|
security:
|
||||||
|
- securityLevel: []
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Reboot initiated
|
||||||
|
'403':
|
||||||
|
description: Security policy violation
|
||||||
|
|
||||||
|
# Configuration Endpoints
|
||||||
|
/manager/preview_method:
|
||||||
|
get:
|
||||||
|
summary: Get or set preview method
|
||||||
|
description: Gets or sets the latent preview method
|
||||||
|
parameters:
|
||||||
|
- name: value
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
description: New preview method
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
enum: [auto, latent2rgb, taesd, none]
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Setting updated or current value returned
|
||||||
|
content:
|
||||||
|
text/plain:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
/manager/db_mode:
|
||||||
|
get:
|
||||||
|
summary: Get or set database mode
|
||||||
|
description: Gets or sets the database mode
|
||||||
|
parameters:
|
||||||
|
- name: value
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
description: New database mode
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
enum: [channel, local, remote]
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Setting updated or current value returned
|
||||||
|
content:
|
||||||
|
text/plain:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
/manager/policy/component:
|
||||||
|
get:
|
||||||
|
summary: Get or set component policy
|
||||||
|
description: Gets or sets the component policy
|
||||||
|
parameters:
|
||||||
|
- name: value
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
description: New component policy
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Setting updated or current value returned
|
||||||
|
content:
|
||||||
|
text/plain:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
/manager/policy/update:
|
||||||
|
get:
|
||||||
|
summary: Get or set update policy
|
||||||
|
description: Gets or sets the update policy
|
||||||
|
parameters:
|
||||||
|
- name: value
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
description: New update policy
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
enum: [stable, nightly, nightly-comfyui]
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Setting updated or current value returned
|
||||||
|
content:
|
||||||
|
text/plain:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
/manager/channel_url_list:
|
||||||
|
get:
|
||||||
|
summary: Get or set channel URL
|
||||||
|
description: Gets or sets the channel URL for custom node sources
|
||||||
|
parameters:
|
||||||
|
- name: value
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
description: New channel name
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Setting updated or channel list returned
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
selected:
|
||||||
|
type: string
|
||||||
|
list:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
url:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
# Component Management Endpoints
|
||||||
|
/manager/component/save:
|
||||||
|
post:
|
||||||
|
summary: Save component
|
||||||
|
description: Saves a reusable workflow component
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
workflow:
|
||||||
|
type: object
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Component saved successfully
|
||||||
|
content:
|
||||||
|
text/plain:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
'400':
|
||||||
|
description: Error saving component
|
||||||
|
|
||||||
|
/manager/component/loads:
|
||||||
|
post:
|
||||||
|
summary: Load components
|
||||||
|
description: Loads all available workflow components
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Components loaded successfully
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
'400':
|
||||||
|
description: Error loading components
|
||||||
|
|
||||||
|
# Miscellaneous Endpoints
|
||||||
|
/manager/version:
|
||||||
|
get:
|
||||||
|
summary: Get manager version
|
||||||
|
description: Returns the current version of ComfyUI-Manager
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
text/plain:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
/manager/notice:
|
||||||
|
get:
|
||||||
|
summary: Get manager notice
|
||||||
|
description: Returns HTML content with notices and version information
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
text/html:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "comfyui-manager"
|
name = "comfyui-manager"
|
||||||
description = "ComfyUI-Manager provides features to install and manage custom nodes for ComfyUI, as well as various functionalities to assist with ComfyUI."
|
description = "ComfyUI-Manager provides features to install and manage custom nodes for ComfyUI, as well as various functionalities to assist with ComfyUI."
|
||||||
version = "3.32.3"
|
version = "3.32.5"
|
||||||
license = { file = "LICENSE.txt" }
|
license = { file = "LICENSE.txt" }
|
||||||
dependencies = ["GitPython", "PyGithub", "matrix-client==0.4.0", "transformers", "huggingface-hub>0.20", "typer", "rich", "typing-extensions", "toml", "uv", "chardet"]
|
dependencies = ["GitPython", "PyGithub", "matrix-client==0.4.0", "transformers", "huggingface-hub>0.20", "typer", "rich", "typing-extensions", "toml", "uv", "chardet"]
|
||||||
|
|
||||||
|
|||||||
@@ -102,12 +102,8 @@ def extract_nodes(code_text):
|
|||||||
def scan_in_file(filename, is_builtin=False):
|
def scan_in_file(filename, is_builtin=False):
|
||||||
global builtin_nodes
|
global builtin_nodes
|
||||||
|
|
||||||
try:
|
with open(filename, encoding='utf-8', errors='ignore') as file:
|
||||||
with open(filename, encoding='utf-8') as file:
|
code = file.read()
|
||||||
code = file.read()
|
|
||||||
except UnicodeDecodeError:
|
|
||||||
with open(filename, encoding='cp949') as file:
|
|
||||||
code = file.read()
|
|
||||||
|
|
||||||
pattern = r"_CLASS_MAPPINGS\s*=\s*{([^}]*)}"
|
pattern = r"_CLASS_MAPPINGS\s*=\s*{([^}]*)}"
|
||||||
regex = re.compile(pattern, re.MULTILINE | re.DOTALL)
|
regex = re.compile(pattern, re.MULTILINE | re.DOTALL)
|
||||||
|
|||||||
19
tests-api/.gitignore
vendored
19
tests-api/.gitignore
vendored
@@ -1,19 +0,0 @@
|
|||||||
# Python cache files
|
|
||||||
__pycache__/
|
|
||||||
*.py[cod]
|
|
||||||
*$py.class
|
|
||||||
|
|
||||||
# Pytest cache
|
|
||||||
.pytest_cache/
|
|
||||||
|
|
||||||
# Coverage reports
|
|
||||||
.coverage
|
|
||||||
htmlcov/
|
|
||||||
|
|
||||||
# Virtual environments
|
|
||||||
venv/
|
|
||||||
env/
|
|
||||||
ENV/
|
|
||||||
|
|
||||||
# Test-specific resources
|
|
||||||
resources/tmp/
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
# ComfyUI-Manager API Tests
|
|
||||||
|
|
||||||
This directory contains tests for the ComfyUI-Manager API endpoints, validating the OpenAPI specification and ensuring API functionality.
|
|
||||||
|
|
||||||
## Setup
|
|
||||||
|
|
||||||
1. Install test dependencies:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install -r requirements-test.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Ensure ComfyUI is running with ComfyUI-Manager installed:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Start ComfyUI with the default server
|
|
||||||
python main.py
|
|
||||||
```
|
|
||||||
|
|
||||||
## Running Tests
|
|
||||||
|
|
||||||
### Run all tests
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pytest -xvs
|
|
||||||
```
|
|
||||||
|
|
||||||
### Run specific test files
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Run only the spec validation tests
|
|
||||||
pytest -xvs test_spec_validation.py
|
|
||||||
|
|
||||||
# Run only the custom node API tests
|
|
||||||
pytest -xvs test_customnode_api.py
|
|
||||||
```
|
|
||||||
|
|
||||||
### Run specific test functions
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Run a specific test
|
|
||||||
pytest -xvs test_customnode_api.py::test_get_custom_node_list
|
|
||||||
```
|
|
||||||
|
|
||||||
## Test Configuration
|
|
||||||
|
|
||||||
The tests use the following default configuration:
|
|
||||||
|
|
||||||
- Server URL: `http://localhost:8188`
|
|
||||||
- Server timeout: 2 seconds
|
|
||||||
- Wait between requests: 0.5 seconds
|
|
||||||
- Maximum retries: 3
|
|
||||||
|
|
||||||
You can override these settings with environment variables:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Use a different server URL
|
|
||||||
COMFYUI_SERVER_URL=http://localhost:8189 pytest -xvs
|
|
||||||
```
|
|
||||||
|
|
||||||
## Test Categories
|
|
||||||
|
|
||||||
The tests are organized into the following categories:
|
|
||||||
|
|
||||||
1. **Spec Validation** (`test_spec_validation.py`): Validates that the OpenAPI specification is correct and complete.
|
|
||||||
2. **Custom Node API** (`test_customnode_api.py`): Tests for custom node management endpoints.
|
|
||||||
3. **Snapshot API** (`test_snapshot_api.py`): Tests for snapshot management endpoints.
|
|
||||||
4. **Queue API** (`test_queue_api.py`): Tests for queue management endpoints.
|
|
||||||
5. **Config API** (`test_config_api.py`): Tests for configuration endpoints.
|
|
||||||
6. **Model API** (`test_model_api.py`): Tests for model management endpoints (minimal as these are being deprecated).
|
|
||||||
|
|
||||||
## Test Implementation Details
|
|
||||||
|
|
||||||
### Fixtures
|
|
||||||
|
|
||||||
- `test_config`: Provides the test configuration
|
|
||||||
- `server_url`: Returns the server URL from the configuration
|
|
||||||
- `openapi_spec`: Loads the OpenAPI specification
|
|
||||||
- `api_client`: Creates a requests Session for API calls
|
|
||||||
- `api_request`: Helper function for making consistent API requests
|
|
||||||
|
|
||||||
### Utilities
|
|
||||||
|
|
||||||
- `validation.py`: Functions for validating responses against the OpenAPI schema
|
|
||||||
- `schema_utils.py`: Utilities for extracting and manipulating schemas
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
- Some tests are skipped with `@pytest.mark.skip` to avoid modifying state in automated testing
|
|
||||||
- Security-level restricted endpoints have minimal tests to avoid security issues
|
|
||||||
- Tests focus on read operations rather than write operations where possible
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# Make tests-api directory a proper package
|
|
||||||
@@ -1,237 +0,0 @@
|
|||||||
"""
|
|
||||||
PyTest configuration and fixtures for API tests.
|
|
||||||
"""
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import json
|
|
||||||
import pytest
|
|
||||||
import requests
|
|
||||||
import tempfile
|
|
||||||
import time
|
|
||||||
import yaml
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Dict, Generator, Optional, Tuple
|
|
||||||
|
|
||||||
# Import test utilities
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
# Get the absolute path to the current file (conftest.py)
|
|
||||||
current_file = Path(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
# Get the directory containing the current file (the tests-api directory)
|
|
||||||
tests_api_dir = current_file.parent
|
|
||||||
|
|
||||||
# Add the tests-api directory to the Python path
|
|
||||||
if str(tests_api_dir) not in sys.path:
|
|
||||||
sys.path.insert(0, str(tests_api_dir))
|
|
||||||
|
|
||||||
# Apply mocks for ComfyUI imports
|
|
||||||
from mocks.patch import apply_mocks
|
|
||||||
apply_mocks()
|
|
||||||
|
|
||||||
# Now we can import from utils.validation
|
|
||||||
from utils.validation import load_openapi_spec
|
|
||||||
|
|
||||||
|
|
||||||
# Default test configuration
|
|
||||||
DEFAULT_TEST_CONFIG = {
|
|
||||||
"server_url": "http://localhost:8188",
|
|
||||||
"server_timeout": 2, # seconds
|
|
||||||
"wait_between_requests": 0.5, # seconds
|
|
||||||
"max_retries": 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
|
||||||
def test_config() -> Dict:
|
|
||||||
"""
|
|
||||||
Load test configuration from environment variables or use defaults.
|
|
||||||
"""
|
|
||||||
config = DEFAULT_TEST_CONFIG.copy()
|
|
||||||
|
|
||||||
# Override from environment variables if present
|
|
||||||
if "COMFYUI_SERVER_URL" in os.environ:
|
|
||||||
config["server_url"] = os.environ["COMFYUI_SERVER_URL"]
|
|
||||||
|
|
||||||
return config
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
|
||||||
def server_url(test_config: Dict) -> str:
|
|
||||||
"""
|
|
||||||
Get the server URL from the test configuration.
|
|
||||||
"""
|
|
||||||
return test_config["server_url"]
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
|
||||||
def openapi_spec() -> Dict:
|
|
||||||
"""
|
|
||||||
Load the OpenAPI specification.
|
|
||||||
"""
|
|
||||||
return load_openapi_spec()
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
|
||||||
def api_client(server_url: str, test_config: Dict) -> requests.Session:
|
|
||||||
"""
|
|
||||||
Create a requests Session for API calls.
|
|
||||||
"""
|
|
||||||
session = requests.Session()
|
|
||||||
|
|
||||||
# Check if the server is running
|
|
||||||
try:
|
|
||||||
response = session.get(f"{server_url}/", timeout=test_config["server_timeout"])
|
|
||||||
response.raise_for_status()
|
|
||||||
except (requests.ConnectionError, requests.Timeout, requests.HTTPError):
|
|
||||||
pytest.skip("ComfyUI server is not running or not accessible")
|
|
||||||
|
|
||||||
return session
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="function")
|
|
||||||
def temp_dir() -> Generator[Path, None, None]:
|
|
||||||
"""
|
|
||||||
Create a temporary directory for test files.
|
|
||||||
"""
|
|
||||||
with tempfile.TemporaryDirectory() as temp_dir:
|
|
||||||
yield Path(temp_dir)
|
|
||||||
|
|
||||||
|
|
||||||
class SecurityLevelContext:
|
|
||||||
"""
|
|
||||||
Context manager for setting and restoring security levels.
|
|
||||||
"""
|
|
||||||
def __init__(self, api_client: requests.Session, server_url: str, security_level: str):
|
|
||||||
self.api_client = api_client
|
|
||||||
self.server_url = server_url
|
|
||||||
self.security_level = security_level
|
|
||||||
self.original_level = None
|
|
||||||
|
|
||||||
async def __aenter__(self):
|
|
||||||
# Get the current security level (not directly exposed in API, would require more setup)
|
|
||||||
# For now, we'll just set the new level
|
|
||||||
|
|
||||||
# Set the new security level
|
|
||||||
# Note: In a real implementation, we would need a way to set this
|
|
||||||
# This is a placeholder - the actual implementation would depend on how
|
|
||||||
# security levels are managed in ComfyUI-Manager
|
|
||||||
return self
|
|
||||||
|
|
||||||
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
||||||
# Restore the original security level if needed
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def security_level_context(api_client: requests.Session, server_url: str):
|
|
||||||
"""
|
|
||||||
Create a context manager for setting security levels.
|
|
||||||
"""
|
|
||||||
return lambda level: SecurityLevelContext(api_client, server_url, level)
|
|
||||||
|
|
||||||
|
|
||||||
def make_api_url(server_url: str, path: str) -> str:
|
|
||||||
"""
|
|
||||||
Construct a full API URL from the server URL and path.
|
|
||||||
"""
|
|
||||||
# Ensure the path starts with a slash
|
|
||||||
if not path.startswith("/"):
|
|
||||||
path = f"/{path}"
|
|
||||||
|
|
||||||
# Remove trailing slash from server_url if present
|
|
||||||
if server_url.endswith("/"):
|
|
||||||
server_url = server_url[:-1]
|
|
||||||
|
|
||||||
return f"{server_url}{path}"
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def api_request(api_client: requests.Session, server_url: str, test_config: Dict):
|
|
||||||
"""
|
|
||||||
Helper function for making API requests with consistent behavior.
|
|
||||||
"""
|
|
||||||
def _request(
|
|
||||||
method: str,
|
|
||||||
path: str,
|
|
||||||
params: Optional[Dict] = None,
|
|
||||||
json_data: Optional[Dict] = None,
|
|
||||||
headers: Optional[Dict] = None,
|
|
||||||
expected_status: int = 200,
|
|
||||||
retry_on_error: bool = True,
|
|
||||||
) -> Tuple[requests.Response, Optional[Dict]]:
|
|
||||||
"""
|
|
||||||
Make an API request with automatic validation.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
method: HTTP method
|
|
||||||
path: API path
|
|
||||||
params: Query parameters
|
|
||||||
json_data: JSON request body
|
|
||||||
headers: HTTP headers
|
|
||||||
expected_status: Expected HTTP status code
|
|
||||||
retry_on_error: Whether to retry on connection errors
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Tuple of (Response object, JSON response data or None)
|
|
||||||
"""
|
|
||||||
method = method.lower()
|
|
||||||
url = make_api_url(server_url, path)
|
|
||||||
|
|
||||||
if headers is None:
|
|
||||||
headers = {}
|
|
||||||
|
|
||||||
# Add common headers
|
|
||||||
headers.setdefault("Accept", "application/json")
|
|
||||||
|
|
||||||
# Sleep between requests to avoid overwhelming the server
|
|
||||||
time.sleep(test_config["wait_between_requests"])
|
|
||||||
|
|
||||||
retries = test_config["max_retries"] if retry_on_error else 0
|
|
||||||
last_exception = None
|
|
||||||
|
|
||||||
for attempt in range(retries + 1):
|
|
||||||
try:
|
|
||||||
if method == "get":
|
|
||||||
response = api_client.get(url, params=params, headers=headers)
|
|
||||||
elif method == "post":
|
|
||||||
response = api_client.post(url, params=params, json=json_data, headers=headers)
|
|
||||||
elif method == "put":
|
|
||||||
response = api_client.put(url, params=params, json=json_data, headers=headers)
|
|
||||||
elif method == "delete":
|
|
||||||
response = api_client.delete(url, params=params, headers=headers)
|
|
||||||
else:
|
|
||||||
raise ValueError(f"Unsupported HTTP method: {method}")
|
|
||||||
|
|
||||||
# Check status code
|
|
||||||
assert response.status_code == expected_status, (
|
|
||||||
f"Expected status code {expected_status}, got {response.status_code}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Parse JSON response if possible
|
|
||||||
json_response = None
|
|
||||||
if response.headers.get("Content-Type", "").startswith("application/json"):
|
|
||||||
try:
|
|
||||||
json_response = response.json()
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
if expected_status == 200:
|
|
||||||
raise ValueError("Response was not valid JSON")
|
|
||||||
|
|
||||||
return response, json_response
|
|
||||||
|
|
||||||
except (requests.ConnectionError, requests.Timeout) as e:
|
|
||||||
last_exception = e
|
|
||||||
if attempt < retries:
|
|
||||||
# Wait before retrying
|
|
||||||
time.sleep(1)
|
|
||||||
continue
|
|
||||||
break
|
|
||||||
|
|
||||||
if last_exception:
|
|
||||||
raise last_exception
|
|
||||||
|
|
||||||
raise RuntimeError("Failed to make API request")
|
|
||||||
|
|
||||||
return _request
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# Make tests-api/mocks directory a proper package
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
"""
|
|
||||||
Mock CustomNodeManager for testing purposes
|
|
||||||
"""
|
|
||||||
|
|
||||||
class CustomNodeManager:
|
|
||||||
"""
|
|
||||||
Mock implementation of the CustomNodeManager class
|
|
||||||
"""
|
|
||||||
instance = None
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.custom_nodes = {}
|
|
||||||
self.node_paths = []
|
|
||||||
self.refresh_timeout = None
|
|
||||||
|
|
||||||
def get_node_path(self, node_class):
|
|
||||||
"""
|
|
||||||
Mock implementation to get the path for a node class
|
|
||||||
"""
|
|
||||||
return self.custom_nodes.get(node_class, None)
|
|
||||||
|
|
||||||
def update_node_paths(self):
|
|
||||||
"""
|
|
||||||
Mock implementation to update node paths
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
"""
|
|
||||||
Patch module to mock imports for testing
|
|
||||||
"""
|
|
||||||
import sys
|
|
||||||
import importlib.util
|
|
||||||
import os
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
# Import mock modules
|
|
||||||
from mocks.prompt_server import PromptServer
|
|
||||||
from mocks.custom_node_manager import CustomNodeManager
|
|
||||||
|
|
||||||
# Current directory
|
|
||||||
current_dir = Path(__file__).parent.parent # tests-api directory
|
|
||||||
|
|
||||||
# Define mocks
|
|
||||||
class MockModule:
|
|
||||||
"""Base class for mock modules"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Create server mock module with PromptServer
|
|
||||||
server_mock = MockModule()
|
|
||||||
server_mock.PromptServer = PromptServer
|
|
||||||
prompt_server_instance = PromptServer()
|
|
||||||
server_mock.PromptServer.instance = prompt_server_instance
|
|
||||||
server_mock.PromptServer.inst = prompt_server_instance
|
|
||||||
|
|
||||||
# Create app mock module with custom_node_manager submodule
|
|
||||||
app_mock = MockModule()
|
|
||||||
app_custom_node_manager = MockModule()
|
|
||||||
app_custom_node_manager.CustomNodeManager = CustomNodeManager
|
|
||||||
app_custom_node_manager.CustomNodeManager.instance = CustomNodeManager()
|
|
||||||
|
|
||||||
# Create utils mock module with json_util submodule
|
|
||||||
utils_mock = MockModule()
|
|
||||||
utils_json_util = MockModule()
|
|
||||||
|
|
||||||
# Create utils.validation and utils.schema_utils submodules
|
|
||||||
utils_validation = MockModule()
|
|
||||||
utils_schema_utils = MockModule()
|
|
||||||
|
|
||||||
# Import actual modules (make sure path is set up correctly)
|
|
||||||
sys.path.insert(0, str(current_dir))
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Import the validation module
|
|
||||||
from utils.validation import load_openapi_spec
|
|
||||||
utils_validation.load_openapi_spec = load_openapi_spec
|
|
||||||
|
|
||||||
# Import all schema_utils functions
|
|
||||||
from utils.schema_utils import (
|
|
||||||
get_all_paths,
|
|
||||||
get_grouped_paths,
|
|
||||||
get_methods_for_path,
|
|
||||||
find_paths_with_security,
|
|
||||||
get_content_types_for_response,
|
|
||||||
get_required_parameters
|
|
||||||
)
|
|
||||||
|
|
||||||
utils_schema_utils.get_all_paths = get_all_paths
|
|
||||||
utils_schema_utils.get_grouped_paths = get_grouped_paths
|
|
||||||
utils_schema_utils.get_methods_for_path = get_methods_for_path
|
|
||||||
utils_schema_utils.find_paths_with_security = find_paths_with_security
|
|
||||||
utils_schema_utils.get_content_types_for_response = get_content_types_for_response
|
|
||||||
utils_schema_utils.get_required_parameters = get_required_parameters
|
|
||||||
|
|
||||||
except ImportError as e:
|
|
||||||
print(f"Error importing test utilities: {e}")
|
|
||||||
# Define dummy functions if imports fail
|
|
||||||
def dummy_load_openapi_spec():
|
|
||||||
"""Dummy function for testing"""
|
|
||||||
return {"paths": {}}
|
|
||||||
utils_validation.load_openapi_spec = dummy_load_openapi_spec
|
|
||||||
|
|
||||||
def dummy_get_all_paths(spec):
|
|
||||||
return list(spec.get("paths", {}).keys())
|
|
||||||
utils_schema_utils.get_all_paths = dummy_get_all_paths
|
|
||||||
|
|
||||||
def dummy_get_grouped_paths(spec):
|
|
||||||
return {}
|
|
||||||
utils_schema_utils.get_grouped_paths = dummy_get_grouped_paths
|
|
||||||
|
|
||||||
def dummy_get_methods_for_path(spec, path):
|
|
||||||
return []
|
|
||||||
utils_schema_utils.get_methods_for_path = dummy_get_methods_for_path
|
|
||||||
|
|
||||||
def dummy_find_paths_with_security(spec, security_scheme=None):
|
|
||||||
return []
|
|
||||||
utils_schema_utils.find_paths_with_security = dummy_find_paths_with_security
|
|
||||||
|
|
||||||
def dummy_get_content_types_for_response(spec, path, method, status_code="200"):
|
|
||||||
return []
|
|
||||||
utils_schema_utils.get_content_types_for_response = dummy_get_content_types_for_response
|
|
||||||
|
|
||||||
def dummy_get_required_parameters(spec, path, method):
|
|
||||||
return []
|
|
||||||
utils_schema_utils.get_required_parameters = dummy_get_required_parameters
|
|
||||||
|
|
||||||
# Add merge_json_recursive from our mock utils
|
|
||||||
from mocks.utils import merge_json_recursive
|
|
||||||
utils_json_util.merge_json_recursive = merge_json_recursive
|
|
||||||
|
|
||||||
# Apply the mocks to sys.modules
|
|
||||||
def apply_mocks():
|
|
||||||
"""Apply all mocks to sys.modules"""
|
|
||||||
sys.modules['server'] = server_mock
|
|
||||||
sys.modules['app'] = app_mock
|
|
||||||
sys.modules['app.custom_node_manager'] = app_custom_node_manager
|
|
||||||
sys.modules['utils'] = utils_mock
|
|
||||||
sys.modules['utils.json_util'] = utils_json_util
|
|
||||||
sys.modules['utils.validation'] = utils_validation
|
|
||||||
sys.modules['utils.schema_utils'] = utils_schema_utils
|
|
||||||
|
|
||||||
# Make sure our actual utils module is importable
|
|
||||||
if current_dir not in sys.path:
|
|
||||||
sys.path.insert(0, str(current_dir))
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
"""
|
|
||||||
Mock PromptServer for testing purposes
|
|
||||||
"""
|
|
||||||
|
|
||||||
class MockRoutes:
|
|
||||||
"""
|
|
||||||
Mock routing class with method decorators
|
|
||||||
"""
|
|
||||||
def __init__(self):
|
|
||||||
self.routes = {}
|
|
||||||
|
|
||||||
def get(self, path):
|
|
||||||
"""Decorator for GET routes"""
|
|
||||||
def decorator(f):
|
|
||||||
self.routes[('GET', path)] = f
|
|
||||||
return f
|
|
||||||
return decorator
|
|
||||||
|
|
||||||
def post(self, path):
|
|
||||||
"""Decorator for POST routes"""
|
|
||||||
def decorator(f):
|
|
||||||
self.routes[('POST', path)] = f
|
|
||||||
return f
|
|
||||||
return decorator
|
|
||||||
|
|
||||||
def put(self, path):
|
|
||||||
"""Decorator for PUT routes"""
|
|
||||||
def decorator(f):
|
|
||||||
self.routes[('PUT', path)] = f
|
|
||||||
return f
|
|
||||||
return decorator
|
|
||||||
|
|
||||||
def delete(self, path):
|
|
||||||
"""Decorator for DELETE routes"""
|
|
||||||
def decorator(f):
|
|
||||||
self.routes[('DELETE', path)] = f
|
|
||||||
return f
|
|
||||||
return decorator
|
|
||||||
|
|
||||||
|
|
||||||
class PromptServer:
|
|
||||||
"""
|
|
||||||
Mock implementation of the PromptServer class
|
|
||||||
"""
|
|
||||||
instance = None
|
|
||||||
inst = None
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.routes = MockRoutes()
|
|
||||||
self.registered_paths = set()
|
|
||||||
self.base_url = "http://127.0.0.1:8188" # Assuming server is running on default port
|
|
||||||
self.queue_lock = None
|
|
||||||
|
|
||||||
def add_route(self, method, path, handler, *args, **kwargs):
|
|
||||||
"""
|
|
||||||
Add a mock route to the server
|
|
||||||
"""
|
|
||||||
self.routes.routes[(method.upper(), path)] = handler
|
|
||||||
self.registered_paths.add(path)
|
|
||||||
|
|
||||||
async def send_msg(self, message, data=None):
|
|
||||||
"""
|
|
||||||
Mock send_msg method (does nothing in the mock)
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def send_sync(self, message, data=None):
|
|
||||||
"""
|
|
||||||
Mock send_sync method (does nothing in the mock)
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
"""
|
|
||||||
Mock utils module for testing purposes
|
|
||||||
"""
|
|
||||||
|
|
||||||
def merge_json_recursive(a, b):
|
|
||||||
"""
|
|
||||||
Mock implementation of merge_json_recursive
|
|
||||||
"""
|
|
||||||
if isinstance(a, dict) and isinstance(b, dict):
|
|
||||||
result = a.copy()
|
|
||||||
for key, value in b.items():
|
|
||||||
if key in result and isinstance(result[key], (dict, list)) and isinstance(value, (dict, list)):
|
|
||||||
result[key] = merge_json_recursive(result[key], value)
|
|
||||||
else:
|
|
||||||
result[key] = value
|
|
||||||
return result
|
|
||||||
elif isinstance(a, list) and isinstance(b, list):
|
|
||||||
return a + b
|
|
||||||
else:
|
|
||||||
return b
|
|
||||||
@@ -1,382 +0,0 @@
|
|||||||
openapi: 3.0.3
|
|
||||||
info:
|
|
||||||
title: ComfyUI-Manager API
|
|
||||||
description: API for managing ComfyUI extensions, custom nodes, and models
|
|
||||||
version: 1.0.0
|
|
||||||
contact:
|
|
||||||
name: ComfyUI Community
|
|
||||||
url: https://github.com/comfyanonymous/ComfyUI
|
|
||||||
|
|
||||||
servers:
|
|
||||||
- url: http://localhost:8188
|
|
||||||
description: Local ComfyUI server
|
|
||||||
|
|
||||||
paths:
|
|
||||||
/customnode/getlist:
|
|
||||||
get:
|
|
||||||
summary: Get the list of custom nodes
|
|
||||||
description: Returns the list of custom nodes from all configured channels
|
|
||||||
parameters:
|
|
||||||
- name: mode
|
|
||||||
in: query
|
|
||||||
description: "The mode to retrieve (local=installed nodes, remote=available nodes)"
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
enum: [local, remote]
|
|
||||||
default: remote
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: List of custom nodes
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
nodes:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: '#/components/schemas/CustomNode'
|
|
||||||
'500':
|
|
||||||
description: Server error
|
|
||||||
|
|
||||||
/customnode/get_node_mappings:
|
|
||||||
get:
|
|
||||||
summary: Get mappings between node class names and their custom nodes
|
|
||||||
description: Returns mappings that help identify which custom node package provides specific node classes
|
|
||||||
parameters:
|
|
||||||
- name: mode
|
|
||||||
in: query
|
|
||||||
description: "The mode for mappings (local=installed nodes, nickname=node nicknames)"
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
enum: [local, nickname]
|
|
||||||
default: local
|
|
||||||
required: true
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Node mappings
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
additionalProperties:
|
|
||||||
type: string
|
|
||||||
'500':
|
|
||||||
description: Server error
|
|
||||||
|
|
||||||
/customnode/get_node_alternatives:
|
|
||||||
get:
|
|
||||||
summary: Get alternative nodes for specific node classes
|
|
||||||
description: Returns alternative implementations of node classes from different custom node packages
|
|
||||||
parameters:
|
|
||||||
- name: mode
|
|
||||||
in: query
|
|
||||||
description: "The mode to retrieve alternatives (local=installed nodes, remote=all available nodes)"
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
enum: [local, remote]
|
|
||||||
default: remote
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Node alternatives
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
additionalProperties:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
'500':
|
|
||||||
description: Server error
|
|
||||||
|
|
||||||
/externalmodel/getlist:
|
|
||||||
get:
|
|
||||||
summary: Get the list of external models
|
|
||||||
description: Returns the list of models from all configured channels
|
|
||||||
parameters:
|
|
||||||
- name: mode
|
|
||||||
in: query
|
|
||||||
description: "The mode to retrieve (local=installed models, remote=available models)"
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
enum: [local, remote]
|
|
||||||
default: remote
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: List of external models
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
models:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: '#/components/schemas/ExternalModel'
|
|
||||||
'500':
|
|
||||||
description: Server error
|
|
||||||
|
|
||||||
/manager/get_config:
|
|
||||||
get:
|
|
||||||
summary: Get manager configuration
|
|
||||||
description: Returns the current configuration of ComfyUI-Manager
|
|
||||||
parameters:
|
|
||||||
- name: key
|
|
||||||
in: query
|
|
||||||
description: "The configuration key to retrieve"
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
required: true
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Configuration value
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
value:
|
|
||||||
type: string
|
|
||||||
'400':
|
|
||||||
description: Invalid key or missing parameter
|
|
||||||
'500':
|
|
||||||
description: Server error
|
|
||||||
|
|
||||||
/manager/set_config:
|
|
||||||
post:
|
|
||||||
summary: Set manager configuration
|
|
||||||
description: Updates the configuration of ComfyUI-Manager
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
required:
|
|
||||||
- key
|
|
||||||
- value
|
|
||||||
properties:
|
|
||||||
key:
|
|
||||||
type: string
|
|
||||||
description: "The configuration key to update"
|
|
||||||
value:
|
|
||||||
type: string
|
|
||||||
description: "The new value for the configuration key"
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Configuration updated successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
success:
|
|
||||||
type: boolean
|
|
||||||
'400':
|
|
||||||
description: Invalid key or value
|
|
||||||
'500':
|
|
||||||
description: Server error
|
|
||||||
|
|
||||||
/snapshot/getlist:
|
|
||||||
get:
|
|
||||||
summary: Get the list of snapshots
|
|
||||||
description: Returns the list of saved snapshots
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: List of snapshots
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
snapshots:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: '#/components/schemas/Snapshot'
|
|
||||||
'500':
|
|
||||||
description: Server error
|
|
||||||
|
|
||||||
/comfyui_manager/queue/status:
|
|
||||||
get:
|
|
||||||
summary: Get queue status
|
|
||||||
description: Returns the current status of the operation queue
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Queue status
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/QueueStatus'
|
|
||||||
'500':
|
|
||||||
description: Server error
|
|
||||||
|
|
||||||
components:
|
|
||||||
schemas:
|
|
||||||
CustomNode:
|
|
||||||
type: object
|
|
||||||
required:
|
|
||||||
- name
|
|
||||||
- title
|
|
||||||
- reference
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
description: "Internal name/ID of the custom node"
|
|
||||||
title:
|
|
||||||
type: string
|
|
||||||
description: "Display title of the custom node"
|
|
||||||
reference:
|
|
||||||
type: string
|
|
||||||
description: "Reference URL (usually GitHub repository URL)"
|
|
||||||
description:
|
|
||||||
type: string
|
|
||||||
description: "Description of what the custom node does"
|
|
||||||
install_type:
|
|
||||||
type: string
|
|
||||||
enum: [git, pip, copy]
|
|
||||||
description: "Installation method for the custom node"
|
|
||||||
files:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
description: "List of files provided by this custom node"
|
|
||||||
node_class_names:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
description: "List of node class names provided by this custom node"
|
|
||||||
installed:
|
|
||||||
type: boolean
|
|
||||||
description: "Whether the custom node is installed"
|
|
||||||
version:
|
|
||||||
type: string
|
|
||||||
description: "Version of the custom node"
|
|
||||||
tags:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
description: "Tags associated with the custom node"
|
|
||||||
|
|
||||||
ExternalModel:
|
|
||||||
type: object
|
|
||||||
required:
|
|
||||||
- name
|
|
||||||
- type
|
|
||||||
- url
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
description: "Name of the model"
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
description: "Type of the model (checkpoint, lora, embedding, etc.)"
|
|
||||||
url:
|
|
||||||
type: string
|
|
||||||
description: "Download URL for the model"
|
|
||||||
description:
|
|
||||||
type: string
|
|
||||||
description: "Description of the model"
|
|
||||||
size:
|
|
||||||
type: integer
|
|
||||||
description: "Size of the model in bytes"
|
|
||||||
installed:
|
|
||||||
type: boolean
|
|
||||||
description: "Whether the model is installed"
|
|
||||||
version:
|
|
||||||
type: string
|
|
||||||
description: "Version of the model"
|
|
||||||
tags:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
description: "Tags associated with the model"
|
|
||||||
|
|
||||||
Snapshot:
|
|
||||||
type: object
|
|
||||||
required:
|
|
||||||
- name
|
|
||||||
- date
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
description: "Name of the snapshot"
|
|
||||||
date:
|
|
||||||
type: string
|
|
||||||
format: date-time
|
|
||||||
description: "Date when the snapshot was created"
|
|
||||||
description:
|
|
||||||
type: string
|
|
||||||
description: "Description of the snapshot"
|
|
||||||
nodes:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
description: "List of custom nodes in the snapshot"
|
|
||||||
models:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
description: "List of models in the snapshot"
|
|
||||||
|
|
||||||
QueueStatus:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
pending:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: '#/components/schemas/QueueItem'
|
|
||||||
description: "List of pending operations in the queue"
|
|
||||||
completed:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: '#/components/schemas/QueueItem'
|
|
||||||
description: "List of completed operations in the queue"
|
|
||||||
failed:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: '#/components/schemas/QueueItem'
|
|
||||||
description: "List of failed operations in the queue"
|
|
||||||
running:
|
|
||||||
type: boolean
|
|
||||||
description: "Whether the queue is currently running"
|
|
||||||
|
|
||||||
QueueItem:
|
|
||||||
type: object
|
|
||||||
required:
|
|
||||||
- id
|
|
||||||
- type
|
|
||||||
- target
|
|
||||||
properties:
|
|
||||||
id:
|
|
||||||
type: string
|
|
||||||
description: "Unique ID of the queue item"
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
enum: [install, update, uninstall]
|
|
||||||
description: "Type of operation"
|
|
||||||
target:
|
|
||||||
type: string
|
|
||||||
description: "Target of the operation (e.g., custom node name, model name)"
|
|
||||||
status:
|
|
||||||
type: string
|
|
||||||
enum: [pending, processing, completed, failed]
|
|
||||||
description: "Current status of the operation"
|
|
||||||
error:
|
|
||||||
type: string
|
|
||||||
description: "Error message if the operation failed"
|
|
||||||
created_at:
|
|
||||||
type: string
|
|
||||||
format: date-time
|
|
||||||
description: "Time when the operation was added to the queue"
|
|
||||||
completed_at:
|
|
||||||
type: string
|
|
||||||
format: date-time
|
|
||||||
description: "Time when the operation was completed"
|
|
||||||
|
|
||||||
securitySchemes:
|
|
||||||
ApiKeyAuth:
|
|
||||||
type: apiKey
|
|
||||||
in: header
|
|
||||||
name: X-API-Key
|
|
||||||
description: "API key for authentication"
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
pytest>=7.3.1
|
|
||||||
requests>=2.31.0
|
|
||||||
openapi-spec-validator>=0.6.0
|
|
||||||
jsonschema>=4.17.3
|
|
||||||
pytest-asyncio>=0.21.0
|
|
||||||
pyyaml>=6.0
|
|
||||||
@@ -1,270 +0,0 @@
|
|||||||
"""
|
|
||||||
Tests for configuration endpoints.
|
|
||||||
"""
|
|
||||||
import pytest
|
|
||||||
from typing import Callable, Dict, List, Tuple
|
|
||||||
|
|
||||||
from utils.validation import validate_response
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_preview_method(
|
|
||||||
api_request: Callable
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test getting the current preview method.
|
|
||||||
"""
|
|
||||||
# Make the API request
|
|
||||||
path = "/manager/preview_method"
|
|
||||||
response, _ = api_request(
|
|
||||||
method="get",
|
|
||||||
path=path,
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify the response is one of the valid preview methods
|
|
||||||
assert response.text in ["auto", "latent2rgb", "taesd", "none"]
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_db_mode(
|
|
||||||
api_request: Callable
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test getting the current database mode.
|
|
||||||
"""
|
|
||||||
# Make the API request
|
|
||||||
path = "/manager/db_mode"
|
|
||||||
response, _ = api_request(
|
|
||||||
method="get",
|
|
||||||
path=path,
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify the response is one of the valid database modes
|
|
||||||
assert response.text in ["channel", "local", "remote"]
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_component_policy(
|
|
||||||
api_request: Callable
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test getting the current component policy.
|
|
||||||
"""
|
|
||||||
# Make the API request
|
|
||||||
path = "/manager/policy/component"
|
|
||||||
response, _ = api_request(
|
|
||||||
method="get",
|
|
||||||
path=path,
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Component policy could be any string
|
|
||||||
assert response.text is not None
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_update_policy(
|
|
||||||
api_request: Callable
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test getting the current update policy.
|
|
||||||
"""
|
|
||||||
# Make the API request
|
|
||||||
path = "/manager/policy/update"
|
|
||||||
response, _ = api_request(
|
|
||||||
method="get",
|
|
||||||
path=path,
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify the response is one of the valid update policies
|
|
||||||
assert response.text in ["stable", "nightly", "nightly-comfyui"]
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_channel_url_list(
|
|
||||||
api_request: Callable,
|
|
||||||
openapi_spec: Dict
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test getting the channel URL list.
|
|
||||||
"""
|
|
||||||
# Make the API request
|
|
||||||
path = "/manager/channel_url_list"
|
|
||||||
response, json_data = api_request(
|
|
||||||
method="get",
|
|
||||||
path=path,
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Validate response structure against the schema
|
|
||||||
assert json_data is not None
|
|
||||||
validate_response(
|
|
||||||
response_data=json_data,
|
|
||||||
path=path,
|
|
||||||
method="get",
|
|
||||||
spec=openapi_spec,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify the response contains the expected fields
|
|
||||||
assert "selected" in json_data
|
|
||||||
assert "list" in json_data
|
|
||||||
assert isinstance(json_data["list"], list)
|
|
||||||
|
|
||||||
# Each channel should have a name and URL
|
|
||||||
if json_data["list"]:
|
|
||||||
first_channel = json_data["list"][0]
|
|
||||||
assert "name" in first_channel
|
|
||||||
assert "url" in first_channel
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_manager_version(
|
|
||||||
api_request: Callable
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test getting the manager version.
|
|
||||||
"""
|
|
||||||
# Make the API request
|
|
||||||
path = "/manager/version"
|
|
||||||
response, _ = api_request(
|
|
||||||
method="get",
|
|
||||||
path=path,
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify the response is a version string
|
|
||||||
assert response.text.startswith("V") # Version strings start with V
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_manager_notice(
|
|
||||||
api_request: Callable
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test getting the manager notice.
|
|
||||||
"""
|
|
||||||
# Make the API request
|
|
||||||
path = "/manager/notice"
|
|
||||||
response, _ = api_request(
|
|
||||||
method="get",
|
|
||||||
path=path,
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify the response is HTML content
|
|
||||||
assert response.headers.get("Content-Type", "").startswith("text/html") or "ComfyUI" in response.text
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason="State-modifying operations")
|
|
||||||
class TestConfigChanges:
|
|
||||||
"""
|
|
||||||
Tests for changing configuration settings.
|
|
||||||
These are skipped to avoid modifying state in automated tests.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@pytest.fixture(scope="class", autouse=True)
|
|
||||||
def save_original_config(self, api_request: Callable):
|
|
||||||
"""
|
|
||||||
Save the original configuration to restore after tests.
|
|
||||||
"""
|
|
||||||
# Save original values
|
|
||||||
response, _ = api_request(
|
|
||||||
method="get",
|
|
||||||
path="/manager/preview_method",
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
self.original_preview_method = response.text
|
|
||||||
|
|
||||||
response, _ = api_request(
|
|
||||||
method="get",
|
|
||||||
path="/manager/db_mode",
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
self.original_db_mode = response.text
|
|
||||||
|
|
||||||
response, _ = api_request(
|
|
||||||
method="get",
|
|
||||||
path="/manager/policy/update",
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
self.original_update_policy = response.text
|
|
||||||
|
|
||||||
yield
|
|
||||||
|
|
||||||
# Restore original values
|
|
||||||
api_request(
|
|
||||||
method="get",
|
|
||||||
path="/manager/preview_method",
|
|
||||||
params={"value": self.original_preview_method},
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
api_request(
|
|
||||||
method="get",
|
|
||||||
path="/manager/db_mode",
|
|
||||||
params={"value": self.original_db_mode},
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
api_request(
|
|
||||||
method="get",
|
|
||||||
path="/manager/policy/update",
|
|
||||||
params={"value": self.original_update_policy},
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_set_preview_method(self, api_request: Callable):
|
|
||||||
"""
|
|
||||||
Test setting the preview method.
|
|
||||||
"""
|
|
||||||
# Set to a different value (taesd)
|
|
||||||
api_request(
|
|
||||||
method="get",
|
|
||||||
path="/manager/preview_method",
|
|
||||||
params={"value": "taesd"},
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify it was changed
|
|
||||||
response, _ = api_request(
|
|
||||||
method="get",
|
|
||||||
path="/manager/preview_method",
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
assert response.text == "taesd"
|
|
||||||
|
|
||||||
def test_set_db_mode(self, api_request: Callable):
|
|
||||||
"""
|
|
||||||
Test setting the database mode.
|
|
||||||
"""
|
|
||||||
# Set to local mode
|
|
||||||
api_request(
|
|
||||||
method="get",
|
|
||||||
path="/manager/db_mode",
|
|
||||||
params={"value": "local"},
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify it was changed
|
|
||||||
response, _ = api_request(
|
|
||||||
method="get",
|
|
||||||
path="/manager/db_mode",
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
assert response.text == "local"
|
|
||||||
|
|
||||||
def test_set_update_policy(self, api_request: Callable):
|
|
||||||
"""
|
|
||||||
Test setting the update policy.
|
|
||||||
"""
|
|
||||||
# Set to stable
|
|
||||||
api_request(
|
|
||||||
method="get",
|
|
||||||
path="/manager/policy/update",
|
|
||||||
params={"value": "stable"},
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify it was changed
|
|
||||||
response, _ = api_request(
|
|
||||||
method="get",
|
|
||||||
path="/manager/policy/update",
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
assert response.text == "stable"
|
|
||||||
@@ -1,200 +0,0 @@
|
|||||||
"""
|
|
||||||
Tests for custom node management endpoints.
|
|
||||||
"""
|
|
||||||
import pytest
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Callable, Dict, Tuple
|
|
||||||
|
|
||||||
from utils.validation import validate_response
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"mode",
|
|
||||||
["local", "remote"]
|
|
||||||
)
|
|
||||||
def test_get_custom_node_list(
|
|
||||||
api_request: Callable,
|
|
||||||
openapi_spec: Dict,
|
|
||||||
mode: str
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test the endpoint for listing custom nodes.
|
|
||||||
"""
|
|
||||||
# Make the API request
|
|
||||||
path = "/customnode/getlist"
|
|
||||||
response, json_data = api_request(
|
|
||||||
method="get",
|
|
||||||
path=path,
|
|
||||||
params={"mode": mode, "skip_update": "true"},
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Validate response structure against the schema
|
|
||||||
assert json_data is not None
|
|
||||||
validate_response(
|
|
||||||
response_data=json_data,
|
|
||||||
path=path,
|
|
||||||
method="get",
|
|
||||||
spec=openapi_spec,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify the response contains the expected fields
|
|
||||||
assert "channel" in json_data
|
|
||||||
assert "node_packs" in json_data
|
|
||||||
assert isinstance(json_data["node_packs"], dict)
|
|
||||||
|
|
||||||
# If there are any node packs, verify they have the expected structure
|
|
||||||
if json_data["node_packs"]:
|
|
||||||
# Take the first node pack to validate
|
|
||||||
first_node_pack = next(iter(json_data["node_packs"].values()))
|
|
||||||
assert "title" in first_node_pack
|
|
||||||
assert "name" in first_node_pack
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_installed_nodes(
|
|
||||||
api_request: Callable,
|
|
||||||
openapi_spec: Dict
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test the endpoint for listing installed nodes.
|
|
||||||
"""
|
|
||||||
# Make the API request
|
|
||||||
path = "/customnode/installed"
|
|
||||||
response, json_data = api_request(
|
|
||||||
method="get",
|
|
||||||
path=path,
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Validate response structure against the schema
|
|
||||||
assert json_data is not None
|
|
||||||
validate_response(
|
|
||||||
response_data=json_data,
|
|
||||||
path=path,
|
|
||||||
method="get",
|
|
||||||
spec=openapi_spec,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify the response is a dictionary of node packs
|
|
||||||
assert isinstance(json_data, dict)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"mode",
|
|
||||||
["local", "nickname"]
|
|
||||||
)
|
|
||||||
def test_get_node_mappings(
|
|
||||||
api_request: Callable,
|
|
||||||
openapi_spec: Dict,
|
|
||||||
mode: str
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test the endpoint for getting node-to-package mappings.
|
|
||||||
"""
|
|
||||||
# Make the API request
|
|
||||||
path = "/customnode/getmappings"
|
|
||||||
response, json_data = api_request(
|
|
||||||
method="get",
|
|
||||||
path=path,
|
|
||||||
params={"mode": mode},
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Validate response structure against the schema
|
|
||||||
assert json_data is not None
|
|
||||||
validate_response(
|
|
||||||
response_data=json_data,
|
|
||||||
path=path,
|
|
||||||
method="get",
|
|
||||||
spec=openapi_spec,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify the response is a dictionary mapping extension IDs to node info
|
|
||||||
assert isinstance(json_data, dict)
|
|
||||||
|
|
||||||
# If there are any mappings, verify they have the expected structure
|
|
||||||
if json_data:
|
|
||||||
# Take the first mapping to validate
|
|
||||||
first_mapping = next(iter(json_data.values()))
|
|
||||||
assert isinstance(first_mapping, list)
|
|
||||||
assert len(first_mapping) == 2
|
|
||||||
assert isinstance(first_mapping[0], list) # List of node classes
|
|
||||||
assert isinstance(first_mapping[1], dict) # Metadata
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"mode",
|
|
||||||
["local", "remote"]
|
|
||||||
)
|
|
||||||
def test_get_node_alternatives(
|
|
||||||
api_request: Callable,
|
|
||||||
openapi_spec: Dict,
|
|
||||||
mode: str
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test the endpoint for getting alternative node options.
|
|
||||||
"""
|
|
||||||
# Make the API request
|
|
||||||
path = "/customnode/alternatives"
|
|
||||||
response, json_data = api_request(
|
|
||||||
method="get",
|
|
||||||
path=path,
|
|
||||||
params={"mode": mode},
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Validate response structure against the schema
|
|
||||||
assert json_data is not None
|
|
||||||
validate_response(
|
|
||||||
response_data=json_data,
|
|
||||||
path=path,
|
|
||||||
method="get",
|
|
||||||
spec=openapi_spec,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify the response is a dictionary
|
|
||||||
assert isinstance(json_data, dict)
|
|
||||||
|
|
||||||
|
|
||||||
def test_fetch_updates(
|
|
||||||
api_request: Callable
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test the endpoint for fetching updates.
|
|
||||||
This might modify state, so we just check for a valid response.
|
|
||||||
"""
|
|
||||||
# Make the API request with skip_update=true to avoid actual updates
|
|
||||||
path = "/customnode/fetch_updates"
|
|
||||||
response, _ = api_request(
|
|
||||||
method="get",
|
|
||||||
path=path,
|
|
||||||
params={"mode": "local"},
|
|
||||||
# Don't validate JSON since this endpoint doesn't return JSON
|
|
||||||
expected_status=200,
|
|
||||||
retry_on_error=False, # Don't retry as this might have side effects
|
|
||||||
)
|
|
||||||
|
|
||||||
# Just check the status code is as expected (covered by api_request)
|
|
||||||
assert response.status_code in [200, 201]
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason="Queue endpoints are better tested with queue operations")
|
|
||||||
def test_queue_update_all(
|
|
||||||
api_request: Callable
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test the endpoint for queuing updates for all nodes.
|
|
||||||
Skipping as this would actually modify the installation.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason="Security-restricted endpoint")
|
|
||||||
def test_install_node_via_git_url(
|
|
||||||
api_request: Callable
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test the endpoint for installing a node via Git URL.
|
|
||||||
Skipping as this requires high security level and would modify the installation.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
# Print current working directory
|
|
||||||
print(f"Current directory: {os.getcwd()}")
|
|
||||||
|
|
||||||
# Print module search path
|
|
||||||
print(f"System path: {sys.path}")
|
|
||||||
|
|
||||||
# Try to import
|
|
||||||
try:
|
|
||||||
from utils.validation import load_openapi_spec
|
|
||||||
print("Import successful!")
|
|
||||||
except ImportError as e:
|
|
||||||
print(f"Import error: {e}")
|
|
||||||
|
|
||||||
# Try direct import
|
|
||||||
try:
|
|
||||||
sys.path.insert(0, os.path.join(os.getcwd(), "custom_nodes/ComfyUI-Manager/tests-api"))
|
|
||||||
from utils.validation import load_openapi_spec
|
|
||||||
print("Direct import successful!")
|
|
||||||
except ImportError as e:
|
|
||||||
print(f"Direct import error: {e}")
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
"""
|
|
||||||
Tests for model management endpoints.
|
|
||||||
These features are scheduled for deprecation, so tests are minimal.
|
|
||||||
"""
|
|
||||||
import pytest
|
|
||||||
from typing import Callable, Dict
|
|
||||||
|
|
||||||
from utils.validation import validate_response
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"mode",
|
|
||||||
["local", "remote"]
|
|
||||||
)
|
|
||||||
def test_get_external_model_list(
|
|
||||||
api_request: Callable,
|
|
||||||
openapi_spec: Dict,
|
|
||||||
mode: str
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test the endpoint for listing external models.
|
|
||||||
"""
|
|
||||||
# Make the API request
|
|
||||||
path = "/externalmodel/getlist"
|
|
||||||
response, json_data = api_request(
|
|
||||||
method="get",
|
|
||||||
path=path,
|
|
||||||
params={"mode": mode},
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Validate response structure against the schema
|
|
||||||
assert json_data is not None
|
|
||||||
validate_response(
|
|
||||||
response_data=json_data,
|
|
||||||
path=path,
|
|
||||||
method="get",
|
|
||||||
spec=openapi_spec,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify the response contains the expected fields
|
|
||||||
assert "models" in json_data
|
|
||||||
assert isinstance(json_data["models"], list)
|
|
||||||
|
|
||||||
# If there are any models, verify they have the expected structure
|
|
||||||
if json_data["models"]:
|
|
||||||
first_model = json_data["models"][0]
|
|
||||||
assert "name" in first_model
|
|
||||||
assert "type" in first_model
|
|
||||||
assert "url" in first_model
|
|
||||||
assert "filename" in first_model
|
|
||||||
assert "installed" in first_model
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason="State-modifying operation that requires auth")
|
|
||||||
def test_install_model():
|
|
||||||
"""
|
|
||||||
Test queuing a model installation.
|
|
||||||
Skipped to avoid modifying state and requires authentication.
|
|
||||||
This feature is also scheduled for deprecation.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
@@ -1,213 +0,0 @@
|
|||||||
"""
|
|
||||||
Tests for queue management endpoints.
|
|
||||||
"""
|
|
||||||
import pytest
|
|
||||||
import time
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Callable, Dict, Tuple
|
|
||||||
|
|
||||||
from utils.validation import validate_response
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_queue_status(
|
|
||||||
api_request: Callable,
|
|
||||||
openapi_spec: Dict
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test the endpoint for getting queue status.
|
|
||||||
"""
|
|
||||||
# Make the API request
|
|
||||||
path = "/manager/queue/status"
|
|
||||||
response, json_data = api_request(
|
|
||||||
method="get",
|
|
||||||
path=path,
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Validate response structure against the schema
|
|
||||||
assert json_data is not None
|
|
||||||
validate_response(
|
|
||||||
response_data=json_data,
|
|
||||||
path=path,
|
|
||||||
method="get",
|
|
||||||
spec=openapi_spec,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify the response contains the expected fields
|
|
||||||
assert "total_count" in json_data
|
|
||||||
assert "done_count" in json_data
|
|
||||||
assert "in_progress_count" in json_data
|
|
||||||
assert "is_processing" in json_data
|
|
||||||
|
|
||||||
# Type checks
|
|
||||||
assert isinstance(json_data["total_count"], int)
|
|
||||||
assert isinstance(json_data["done_count"], int)
|
|
||||||
assert isinstance(json_data["in_progress_count"], int)
|
|
||||||
assert isinstance(json_data["is_processing"], bool)
|
|
||||||
|
|
||||||
|
|
||||||
def test_reset_queue(
|
|
||||||
api_request: Callable
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test the endpoint for resetting the queue.
|
|
||||||
"""
|
|
||||||
# Make the API request
|
|
||||||
path = "/manager/queue/reset"
|
|
||||||
response, _ = api_request(
|
|
||||||
method="get",
|
|
||||||
path=path,
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Now check the queue status to verify it was reset
|
|
||||||
response2, json_data = api_request(
|
|
||||||
method="get",
|
|
||||||
path="/manager/queue/status",
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Queue should be empty after reset
|
|
||||||
assert json_data["total_count"] == json_data["done_count"] + json_data["in_progress_count"]
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason="State-modifying operation that requires auth")
|
|
||||||
def test_queue_install_node():
|
|
||||||
"""
|
|
||||||
Test queuing a node installation.
|
|
||||||
Skipped to avoid modifying state and requires authentication.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason="State-modifying operation that requires auth")
|
|
||||||
def test_queue_update_node():
|
|
||||||
"""
|
|
||||||
Test queuing a node update.
|
|
||||||
Skipped to avoid modifying state and requires authentication.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason="State-modifying operation that requires auth")
|
|
||||||
def test_queue_uninstall_node():
|
|
||||||
"""
|
|
||||||
Test queuing a node uninstallation.
|
|
||||||
Skipped to avoid modifying state and requires authentication.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason="State-modifying operation")
|
|
||||||
def test_queue_start():
|
|
||||||
"""
|
|
||||||
Test starting the queue.
|
|
||||||
Skipped to avoid modifying state.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class TestQueueOperations:
|
|
||||||
"""
|
|
||||||
Test a complete queue workflow.
|
|
||||||
These tests are grouped to ensure proper sequencing but are still skipped
|
|
||||||
to avoid modifying state in automated tests.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@pytest.fixture(scope="class")
|
|
||||||
def node_data(self) -> Dict:
|
|
||||||
"""
|
|
||||||
Create test data for a node operation.
|
|
||||||
"""
|
|
||||||
# This would be replaced with actual data for a known safe node
|
|
||||||
return {
|
|
||||||
"ui_id": "test_node_1",
|
|
||||||
"id": "comfyui-manager", # Manager itself
|
|
||||||
"version": "latest",
|
|
||||||
"channel": "default",
|
|
||||||
"mode": "local",
|
|
||||||
}
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason="State-modifying operation")
|
|
||||||
def test_queue_operation_sequence(
|
|
||||||
self,
|
|
||||||
api_request: Callable,
|
|
||||||
node_data: Dict
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test the queue operation sequence.
|
|
||||||
"""
|
|
||||||
# 1. Reset the queue
|
|
||||||
api_request(
|
|
||||||
method="get",
|
|
||||||
path="/manager/queue/reset",
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# 2. Queue a node operation (we'll use the manager itself)
|
|
||||||
api_request(
|
|
||||||
method="post",
|
|
||||||
path="/manager/queue/update",
|
|
||||||
json_data=node_data,
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# 3. Check queue status - should have one operation
|
|
||||||
response, json_data = api_request(
|
|
||||||
method="get",
|
|
||||||
path="/manager/queue/status",
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
assert json_data["total_count"] > 0
|
|
||||||
assert not json_data["is_processing"] # Queue hasn't started yet
|
|
||||||
|
|
||||||
# 4. Start the queue
|
|
||||||
api_request(
|
|
||||||
method="get",
|
|
||||||
path="/manager/queue/start",
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# 5. Check queue status again - should be processing
|
|
||||||
response, json_data = api_request(
|
|
||||||
method="get",
|
|
||||||
path="/manager/queue/status",
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Queue should be processing or already done
|
|
||||||
assert json_data["is_processing"] or json_data["done_count"] == json_data["total_count"]
|
|
||||||
|
|
||||||
# 6. Wait for queue to complete (with timeout)
|
|
||||||
max_wait_time = 60 # seconds
|
|
||||||
start_time = time.time()
|
|
||||||
completed = False
|
|
||||||
|
|
||||||
while time.time() - start_time < max_wait_time:
|
|
||||||
response, json_data = api_request(
|
|
||||||
method="get",
|
|
||||||
path="/manager/queue/status",
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
if json_data["done_count"] == json_data["total_count"] and not json_data["is_processing"]:
|
|
||||||
completed = True
|
|
||||||
break
|
|
||||||
|
|
||||||
time.sleep(2) # Wait before checking again
|
|
||||||
|
|
||||||
assert completed, "Queue did not complete within timeout period"
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason="State-modifying operation")
|
|
||||||
def test_concurrent_queue_operations(
|
|
||||||
self,
|
|
||||||
api_request: Callable,
|
|
||||||
node_data: Dict
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test concurrent queue operations.
|
|
||||||
"""
|
|
||||||
# This would test adding multiple operations to the queue
|
|
||||||
# and verifying they all complete correctly
|
|
||||||
pass
|
|
||||||
@@ -1,198 +0,0 @@
|
|||||||
"""
|
|
||||||
Tests for snapshot management endpoints.
|
|
||||||
"""
|
|
||||||
import pytest
|
|
||||||
import time
|
|
||||||
from datetime import datetime
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Callable, Dict, List, Optional
|
|
||||||
|
|
||||||
from utils.validation import validate_response
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_snapshot_list(
|
|
||||||
api_request: Callable,
|
|
||||||
openapi_spec: Dict
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test the endpoint for listing snapshots.
|
|
||||||
"""
|
|
||||||
# Make the API request
|
|
||||||
path = "/snapshot/getlist"
|
|
||||||
response, json_data = api_request(
|
|
||||||
method="get",
|
|
||||||
path=path,
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Validate response structure against the schema
|
|
||||||
assert json_data is not None
|
|
||||||
validate_response(
|
|
||||||
response_data=json_data,
|
|
||||||
path=path,
|
|
||||||
method="get",
|
|
||||||
spec=openapi_spec,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify the response contains the expected fields
|
|
||||||
assert "items" in json_data
|
|
||||||
assert isinstance(json_data["items"], list)
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_current_snapshot(
|
|
||||||
api_request: Callable,
|
|
||||||
openapi_spec: Dict
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test the endpoint for getting the current snapshot.
|
|
||||||
"""
|
|
||||||
# Make the API request
|
|
||||||
path = "/snapshot/get_current"
|
|
||||||
response, json_data = api_request(
|
|
||||||
method="get",
|
|
||||||
path=path,
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Validate response structure against the schema
|
|
||||||
assert json_data is not None
|
|
||||||
validate_response(
|
|
||||||
response_data=json_data,
|
|
||||||
path=path,
|
|
||||||
method="get",
|
|
||||||
spec=openapi_spec,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check for basic snapshot structure
|
|
||||||
assert "snapshot_date" in json_data
|
|
||||||
assert "custom_nodes" in json_data
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason="This test creates a snapshot which is a state-modifying operation")
|
|
||||||
def test_save_snapshot(
|
|
||||||
api_request: Callable
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test the endpoint for saving a new snapshot.
|
|
||||||
Skipped to avoid modifying state in tests.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason="This test removes a snapshot which is a destructive operation")
|
|
||||||
def test_remove_snapshot(
|
|
||||||
api_request: Callable
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test the endpoint for removing a snapshot.
|
|
||||||
Skipped to avoid modifying state in tests.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason="This test restores a snapshot which is a state-modifying operation")
|
|
||||||
def test_restore_snapshot(
|
|
||||||
api_request: Callable
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test the endpoint for restoring a snapshot.
|
|
||||||
Skipped to avoid modifying state in tests.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class TestSnapshotWorkflow:
|
|
||||||
"""
|
|
||||||
Test the complete snapshot workflow (create, list, get, remove).
|
|
||||||
These tests are grouped to ensure proper sequencing but are still skipped
|
|
||||||
to avoid modifying state in automated tests.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@pytest.fixture(scope="class")
|
|
||||||
def snapshot_name(self) -> str:
|
|
||||||
"""
|
|
||||||
Generate a unique snapshot name for testing.
|
|
||||||
"""
|
|
||||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
||||||
return f"test_snapshot_{timestamp}"
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason="State-modifying test")
|
|
||||||
def test_create_snapshot(
|
|
||||||
self,
|
|
||||||
api_request: Callable,
|
|
||||||
snapshot_name: str
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test creating a snapshot.
|
|
||||||
"""
|
|
||||||
# Make the API request to save a snapshot
|
|
||||||
response, _ = api_request(
|
|
||||||
method="get",
|
|
||||||
path="/snapshot/save",
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify a snapshot was created (would need to check the snapshot list)
|
|
||||||
response2, json_data = api_request(
|
|
||||||
method="get",
|
|
||||||
path="/snapshot/getlist",
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# The most recently created snapshot should be first in the list
|
|
||||||
assert json_data["items"]
|
|
||||||
|
|
||||||
# Store the snapshot name for later tests
|
|
||||||
self.actual_snapshot_name = json_data["items"][0]
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason="State-modifying test")
|
|
||||||
def test_get_snapshot_details(
|
|
||||||
self,
|
|
||||||
api_request: Callable,
|
|
||||||
openapi_spec: Dict
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test getting details of the created snapshot.
|
|
||||||
"""
|
|
||||||
# This would check the current snapshot, not a specific one
|
|
||||||
# since there's no direct API to get a specific snapshot
|
|
||||||
response, json_data = api_request(
|
|
||||||
method="get",
|
|
||||||
path="/snapshot/get_current",
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Validate the snapshot data
|
|
||||||
assert json_data is not None
|
|
||||||
validate_response(
|
|
||||||
response_data=json_data,
|
|
||||||
path="/snapshot/get_current",
|
|
||||||
method="get",
|
|
||||||
spec=openapi_spec,
|
|
||||||
)
|
|
||||||
|
|
||||||
@pytest.mark.skip(reason="State-modifying test")
|
|
||||||
def test_remove_test_snapshot(
|
|
||||||
self,
|
|
||||||
api_request: Callable
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test removing the test snapshot.
|
|
||||||
"""
|
|
||||||
# Make the API request to remove the snapshot
|
|
||||||
response, _ = api_request(
|
|
||||||
method="get",
|
|
||||||
path="/snapshot/remove",
|
|
||||||
params={"target": self.actual_snapshot_name},
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Verify the snapshot was removed
|
|
||||||
response2, json_data = api_request(
|
|
||||||
method="get",
|
|
||||||
path="/snapshot/getlist",
|
|
||||||
expected_status=200,
|
|
||||||
)
|
|
||||||
|
|
||||||
# The snapshot should no longer be in the list
|
|
||||||
assert self.actual_snapshot_name not in json_data["items"]
|
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
"""
|
|
||||||
Tests for validating the OpenAPI specification.
|
|
||||||
"""
|
|
||||||
import json
|
|
||||||
import pytest
|
|
||||||
import yaml
|
|
||||||
from typing import Dict, Any, List, Tuple
|
|
||||||
from pathlib import Path
|
|
||||||
from openapi_spec_validator import validate_spec
|
|
||||||
from utils.validation import load_openapi_spec
|
|
||||||
from utils.schema_utils import (
|
|
||||||
get_all_paths,
|
|
||||||
get_methods_for_path,
|
|
||||||
find_paths_with_security,
|
|
||||||
get_required_parameters
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_spec_is_valid():
|
|
||||||
"""
|
|
||||||
Test that the OpenAPI specification is valid according to the spec validator.
|
|
||||||
"""
|
|
||||||
spec = load_openapi_spec()
|
|
||||||
validate_spec(spec)
|
|
||||||
|
|
||||||
|
|
||||||
def test_spec_has_info():
|
|
||||||
"""
|
|
||||||
Test that the OpenAPI specification has basic info.
|
|
||||||
"""
|
|
||||||
spec = load_openapi_spec()
|
|
||||||
|
|
||||||
assert "info" in spec
|
|
||||||
assert "title" in spec["info"]
|
|
||||||
assert "version" in spec["info"]
|
|
||||||
assert spec["info"]["title"] == "ComfyUI-Manager API"
|
|
||||||
|
|
||||||
|
|
||||||
def test_spec_has_paths():
|
|
||||||
"""
|
|
||||||
Test that the OpenAPI specification has paths defined.
|
|
||||||
"""
|
|
||||||
spec = load_openapi_spec()
|
|
||||||
|
|
||||||
assert "paths" in spec
|
|
||||||
assert len(spec["paths"]) > 0
|
|
||||||
|
|
||||||
|
|
||||||
def test_paths_have_responses():
|
|
||||||
"""
|
|
||||||
Test that all paths have responses defined.
|
|
||||||
"""
|
|
||||||
spec = load_openapi_spec()
|
|
||||||
|
|
||||||
for path, path_item in spec["paths"].items():
|
|
||||||
for method, operation in path_item.items():
|
|
||||||
if method.lower() not in {"get", "post", "put", "delete", "patch", "options", "head"}:
|
|
||||||
continue
|
|
||||||
|
|
||||||
assert "responses" in operation, f"Path {path} method {method} has no responses"
|
|
||||||
assert len(operation["responses"]) > 0, f"Path {path} method {method} has empty responses"
|
|
||||||
|
|
||||||
|
|
||||||
def test_responses_have_schemas():
|
|
||||||
"""
|
|
||||||
Test that responses with application/json content type have schemas.
|
|
||||||
"""
|
|
||||||
spec = load_openapi_spec()
|
|
||||||
|
|
||||||
for path, path_item in spec["paths"].items():
|
|
||||||
for method, operation in path_item.items():
|
|
||||||
if method.lower() not in {"get", "post", "put", "delete", "patch", "options", "head"}:
|
|
||||||
continue
|
|
||||||
|
|
||||||
for status, response in operation["responses"].items():
|
|
||||||
if "content" not in response:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if "application/json" in response["content"]:
|
|
||||||
assert "schema" in response["content"]["application/json"], (
|
|
||||||
f"Path {path} method {method} status {status} "
|
|
||||||
f"application/json content has no schema"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_required_parameters_have_schemas():
|
|
||||||
"""
|
|
||||||
Test that all required parameters have schemas.
|
|
||||||
"""
|
|
||||||
spec = load_openapi_spec()
|
|
||||||
|
|
||||||
for path, path_item in spec["paths"].items():
|
|
||||||
for method, operation in path_item.items():
|
|
||||||
if method.lower() not in {"get", "post", "put", "delete", "patch", "options", "head"}:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if "parameters" not in operation:
|
|
||||||
continue
|
|
||||||
|
|
||||||
for param in operation["parameters"]:
|
|
||||||
if param.get("required", False):
|
|
||||||
assert "schema" in param, (
|
|
||||||
f"Path {path} method {method} required parameter {param.get('name')} has no schema"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_security_schemes_defined():
|
|
||||||
"""
|
|
||||||
Test that security schemes are properly defined.
|
|
||||||
"""
|
|
||||||
spec = load_openapi_spec()
|
|
||||||
|
|
||||||
# Get paths requiring security
|
|
||||||
secure_paths = find_paths_with_security(spec)
|
|
||||||
|
|
||||||
if secure_paths:
|
|
||||||
assert "components" in spec, "Spec has secure paths but no components"
|
|
||||||
assert "securitySchemes" in spec["components"], "Spec has secure paths but no securitySchemes"
|
|
||||||
|
|
||||||
# Check each security reference is defined
|
|
||||||
for path, method in secure_paths:
|
|
||||||
operation = spec["paths"][path][method]
|
|
||||||
for security_req in operation["security"]:
|
|
||||||
for scheme_name in security_req:
|
|
||||||
assert scheme_name in spec["components"]["securitySchemes"], (
|
|
||||||
f"Security scheme {scheme_name} used by {method.upper()} {path} "
|
|
||||||
f"is not defined in components.securitySchemes"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_common_endpoint_groups_present():
|
|
||||||
"""
|
|
||||||
Test that the spec includes the main endpoint groups.
|
|
||||||
"""
|
|
||||||
spec = load_openapi_spec()
|
|
||||||
paths = get_all_paths(spec)
|
|
||||||
|
|
||||||
# Define the expected endpoint prefixes
|
|
||||||
expected_prefixes = [
|
|
||||||
"/customnode/",
|
|
||||||
"/externalmodel/",
|
|
||||||
"/manager/",
|
|
||||||
"/snapshot/",
|
|
||||||
"/comfyui_manager/",
|
|
||||||
]
|
|
||||||
|
|
||||||
# Check that at least one path exists for each expected prefix
|
|
||||||
for prefix in expected_prefixes:
|
|
||||||
matching_paths = [p for p in paths if p.startswith(prefix)]
|
|
||||||
assert matching_paths, f"No endpoints found with prefix {prefix}"
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# Make utils directory a proper package
|
|
||||||
@@ -1,174 +0,0 @@
|
|||||||
"""
|
|
||||||
Schema utilities for extracting and manipulating OpenAPI schemas.
|
|
||||||
"""
|
|
||||||
import json
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Any, Dict, List, Optional, Set, Tuple
|
|
||||||
from .validation import load_openapi_spec
|
|
||||||
|
|
||||||
|
|
||||||
def get_all_paths(spec: Dict[str, Any]) -> List[str]:
|
|
||||||
"""
|
|
||||||
Get all paths defined in the OpenAPI specification.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
spec: The OpenAPI specification
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
List of all paths
|
|
||||||
"""
|
|
||||||
return list(spec.get("paths", {}).keys())
|
|
||||||
|
|
||||||
|
|
||||||
def get_grouped_paths(spec: Dict[str, Any]) -> Dict[str, List[str]]:
|
|
||||||
"""
|
|
||||||
Group paths by their top-level segment.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
spec: The OpenAPI specification
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Dictionary mapping top-level segments to lists of paths
|
|
||||||
"""
|
|
||||||
result = {}
|
|
||||||
|
|
||||||
for path in get_all_paths(spec):
|
|
||||||
segments = path.strip("/").split("/")
|
|
||||||
if not segments:
|
|
||||||
continue
|
|
||||||
|
|
||||||
top_segment = segments[0]
|
|
||||||
if top_segment not in result:
|
|
||||||
result[top_segment] = []
|
|
||||||
|
|
||||||
result[top_segment].append(path)
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def get_methods_for_path(spec: Dict[str, Any], path: str) -> List[str]:
|
|
||||||
"""
|
|
||||||
Get all HTTP methods defined for a path.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
spec: The OpenAPI specification
|
|
||||||
path: The API path
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
List of HTTP methods (lowercase)
|
|
||||||
"""
|
|
||||||
if path not in spec.get("paths", {}):
|
|
||||||
return []
|
|
||||||
|
|
||||||
return [
|
|
||||||
method.lower()
|
|
||||||
for method in spec["paths"][path].keys()
|
|
||||||
if method.lower() in {"get", "post", "put", "delete", "patch", "options", "head"}
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def find_paths_with_security(
|
|
||||||
spec: Dict[str, Any],
|
|
||||||
security_scheme: Optional[str] = None
|
|
||||||
) -> List[Tuple[str, str]]:
|
|
||||||
"""
|
|
||||||
Find all paths that require security.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
spec: The OpenAPI specification
|
|
||||||
security_scheme: Optional specific security scheme to filter by
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
List of (path, method) tuples that require security
|
|
||||||
"""
|
|
||||||
result = []
|
|
||||||
|
|
||||||
for path, path_item in spec.get("paths", {}).items():
|
|
||||||
for method, operation in path_item.items():
|
|
||||||
if method.lower() not in {"get", "post", "put", "delete", "patch", "options", "head"}:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if "security" in operation:
|
|
||||||
if security_scheme is None:
|
|
||||||
result.append((path, method.lower()))
|
|
||||||
else:
|
|
||||||
# Check if this security scheme is required
|
|
||||||
for security_req in operation["security"]:
|
|
||||||
if security_scheme in security_req:
|
|
||||||
result.append((path, method.lower()))
|
|
||||||
break
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def get_content_types_for_response(
|
|
||||||
spec: Dict[str, Any],
|
|
||||||
path: str,
|
|
||||||
method: str,
|
|
||||||
status_code: str = "200"
|
|
||||||
) -> List[str]:
|
|
||||||
"""
|
|
||||||
Get content types defined for a response.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
spec: The OpenAPI specification
|
|
||||||
path: The API path
|
|
||||||
method: The HTTP method
|
|
||||||
status_code: The HTTP status code
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
List of content types
|
|
||||||
"""
|
|
||||||
method = method.lower()
|
|
||||||
|
|
||||||
if path not in spec["paths"]:
|
|
||||||
return []
|
|
||||||
|
|
||||||
if method not in spec["paths"][path]:
|
|
||||||
return []
|
|
||||||
|
|
||||||
if "responses" not in spec["paths"][path][method]:
|
|
||||||
return []
|
|
||||||
|
|
||||||
if status_code not in spec["paths"][path][method]["responses"]:
|
|
||||||
return []
|
|
||||||
|
|
||||||
response_def = spec["paths"][path][method]["responses"][status_code]
|
|
||||||
|
|
||||||
if "content" not in response_def:
|
|
||||||
return []
|
|
||||||
|
|
||||||
return list(response_def["content"].keys())
|
|
||||||
|
|
||||||
|
|
||||||
def get_required_parameters(
|
|
||||||
spec: Dict[str, Any],
|
|
||||||
path: str,
|
|
||||||
method: str
|
|
||||||
) -> List[Dict[str, Any]]:
|
|
||||||
"""
|
|
||||||
Get all required parameters for a path/method.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
spec: The OpenAPI specification
|
|
||||||
path: The API path
|
|
||||||
method: The HTTP method
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
List of parameter objects that are required
|
|
||||||
"""
|
|
||||||
method = method.lower()
|
|
||||||
|
|
||||||
if path not in spec["paths"]:
|
|
||||||
return []
|
|
||||||
|
|
||||||
if method not in spec["paths"][path]:
|
|
||||||
return []
|
|
||||||
|
|
||||||
if "parameters" not in spec["paths"][path][method]:
|
|
||||||
return []
|
|
||||||
|
|
||||||
return [
|
|
||||||
param for param in spec["paths"][path][method]["parameters"]
|
|
||||||
if param.get("required", False)
|
|
||||||
]
|
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
"""
|
|
||||||
Validation utilities for API tests.
|
|
||||||
"""
|
|
||||||
import json
|
|
||||||
import jsonschema
|
|
||||||
import yaml
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Any, Dict, Optional, Union
|
|
||||||
|
|
||||||
|
|
||||||
def load_openapi_spec(spec_path: Union[str, Path] = None) -> Dict[str, Any]:
|
|
||||||
"""
|
|
||||||
Load the OpenAPI specification document.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
spec_path: Path to the OpenAPI specification file
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The OpenAPI specification as a dictionary
|
|
||||||
"""
|
|
||||||
if spec_path is None:
|
|
||||||
# Default to the root openapi.yaml file
|
|
||||||
spec_path = Path(__file__).parents[2] / "openapi.yaml"
|
|
||||||
|
|
||||||
with open(spec_path, "r") as f:
|
|
||||||
if str(spec_path).endswith(".yaml") or str(spec_path).endswith(".yml"):
|
|
||||||
return yaml.safe_load(f)
|
|
||||||
else:
|
|
||||||
return json.load(f)
|
|
||||||
|
|
||||||
|
|
||||||
def get_schema_for_path(
|
|
||||||
spec: Dict[str, Any],
|
|
||||||
path: str,
|
|
||||||
method: str,
|
|
||||||
status_code: str = "200",
|
|
||||||
content_type: str = "application/json"
|
|
||||||
) -> Optional[Dict[str, Any]]:
|
|
||||||
"""
|
|
||||||
Extract the response schema for a specific path, method, and status code.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
spec: The OpenAPI specification
|
|
||||||
path: The API path (e.g., "/customnode/getlist")
|
|
||||||
method: The HTTP method (e.g., "get", "post")
|
|
||||||
status_code: The HTTP status code (default: "200")
|
|
||||||
content_type: The response content type (default: "application/json")
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The schema for the specified path and method, or None if not found
|
|
||||||
"""
|
|
||||||
method = method.lower()
|
|
||||||
|
|
||||||
if path not in spec["paths"]:
|
|
||||||
return None
|
|
||||||
|
|
||||||
if method not in spec["paths"][path]:
|
|
||||||
return None
|
|
||||||
|
|
||||||
if "responses" not in spec["paths"][path][method]:
|
|
||||||
return None
|
|
||||||
|
|
||||||
if status_code not in spec["paths"][path][method]["responses"]:
|
|
||||||
return None
|
|
||||||
|
|
||||||
response_def = spec["paths"][path][method]["responses"][status_code]
|
|
||||||
|
|
||||||
if "content" not in response_def:
|
|
||||||
return None
|
|
||||||
|
|
||||||
if content_type not in response_def["content"]:
|
|
||||||
return None
|
|
||||||
|
|
||||||
if "schema" not in response_def["content"][content_type]:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return response_def["content"][content_type]["schema"]
|
|
||||||
|
|
||||||
|
|
||||||
def validate_response_schema(
|
|
||||||
response_data: Any,
|
|
||||||
schema: Dict[str, Any],
|
|
||||||
spec: Dict[str, Any] = None
|
|
||||||
) -> bool:
|
|
||||||
"""
|
|
||||||
Validate a response against a schema from the OpenAPI specification.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
response_data: The response data to validate
|
|
||||||
schema: The schema to validate against
|
|
||||||
spec: The complete OpenAPI specification (for resolving references)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
True if validation succeeds, raises an exception otherwise
|
|
||||||
"""
|
|
||||||
if spec is None:
|
|
||||||
spec = load_openapi_spec()
|
|
||||||
|
|
||||||
# Create a resolver for references within the schema
|
|
||||||
resolver = jsonschema.RefResolver.from_schema(spec)
|
|
||||||
|
|
||||||
# Validate the response against the schema
|
|
||||||
jsonschema.validate(
|
|
||||||
instance=response_data,
|
|
||||||
schema=schema,
|
|
||||||
resolver=resolver
|
|
||||||
)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def validate_response(
|
|
||||||
response_data: Any,
|
|
||||||
path: str,
|
|
||||||
method: str,
|
|
||||||
status_code: str = "200",
|
|
||||||
content_type: str = "application/json",
|
|
||||||
spec: Dict[str, Any] = None
|
|
||||||
) -> bool:
|
|
||||||
"""
|
|
||||||
Validate a response against the schema defined in the OpenAPI specification.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
response_data: The response data to validate
|
|
||||||
path: The API path
|
|
||||||
method: The HTTP method
|
|
||||||
status_code: The HTTP status code (default: "200")
|
|
||||||
content_type: The response content type (default: "application/json")
|
|
||||||
spec: The OpenAPI specification (loaded from default location if None)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
True if validation succeeds, raises an exception otherwise
|
|
||||||
"""
|
|
||||||
if spec is None:
|
|
||||||
spec = load_openapi_spec()
|
|
||||||
|
|
||||||
schema = get_schema_for_path(
|
|
||||||
spec=spec,
|
|
||||||
path=path,
|
|
||||||
method=method,
|
|
||||||
status_code=status_code,
|
|
||||||
content_type=content_type
|
|
||||||
)
|
|
||||||
|
|
||||||
if schema is None:
|
|
||||||
raise ValueError(
|
|
||||||
f"No schema found for {method.upper()} {path} "
|
|
||||||
f"with status {status_code} and content type {content_type}"
|
|
||||||
)
|
|
||||||
|
|
||||||
return validate_response_schema(
|
|
||||||
response_data=response_data,
|
|
||||||
schema=schema,
|
|
||||||
spec=spec
|
|
||||||
)
|
|
||||||
Reference in New Issue
Block a user