mirror of
https://github.com/Comfy-Org/ComfyUI-Manager.git
synced 2026-05-24 07:47:24 +08:00
Compare commits
9 Commits
aa09e57dbb
...
dcdc166427
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dcdc166427 | ||
|
|
e8e0e884f2 | ||
|
|
379fad3809 | ||
|
|
bb0ef5bdc3 | ||
|
|
9617b0e56e | ||
|
|
1bdcd1bdbf | ||
|
|
e04ed0eda7 | ||
|
|
02aa67b541 | ||
|
|
67d03530a3 |
@ -9596,6 +9596,16 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "Automatically archives generated files to Amazon S3 or S3-compatible storage services"
|
||||
},
|
||||
{
|
||||
"author": "olduvai-jp",
|
||||
"title": "ComfyUI-S3-IO",
|
||||
"reference": "https://github.com/olduvai-jp/ComfyUI-S3-IO",
|
||||
"files": [
|
||||
"https://github.com/olduvai-jp/ComfyUI-S3-IO"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "S3-backed input/output nodes for ComfyUI to browse, load images/videos from S3 buckets and push outputs back to S3 automatically."
|
||||
},
|
||||
{
|
||||
"author": "AiMiDi",
|
||||
"title": "ComfyUI-Aimidi-nodes",
|
||||
@ -12905,6 +12915,16 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "A visual ComfyUI latent canvas dimensions selector"
|
||||
},
|
||||
{
|
||||
"author": "GraftingRayman",
|
||||
"title": "ComfyUI-Games",
|
||||
"reference": "https://github.com/GraftingRayman/ComfyUI-Games",
|
||||
"files": [
|
||||
"https://github.com/GraftingRayman/ComfyUI-Games"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI node providing Tetris game functionality. (Description by CC)"
|
||||
},
|
||||
{
|
||||
"author": "royceschultz",
|
||||
"title": "ComfyUI-Notifications",
|
||||
@ -16841,6 +16861,16 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "This repository provides a custom ComfyUI node for running object detection with the [a/Qwen 2.5 VL](https://github.com/QwenLM/Qwen2.5-VL) model. The node downloads the selected model on demand, runs a detection prompt and outputs bounding boxes that can be used with segmentation nodes such as [a/SAM2](https://github.com/kijai/ComfyUI-segment-anything-2)."
|
||||
},
|
||||
{
|
||||
"author": "TTPlanetPig",
|
||||
"title": "Comfyui_DreamID-V_wrapper",
|
||||
"reference": "https://github.com/TTPlanetPig/Comfyui_DreamID-V_wrapper",
|
||||
"files": [
|
||||
"https://github.com/TTPlanetPig/Comfyui_DreamID-V_wrapper"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A simple and efficient ComfyUI integration for DreamID-V, a model for identity-preserving video generation that animates reference images using motion from pose videos."
|
||||
},
|
||||
{
|
||||
"author": "camenduru",
|
||||
"title": "ComfyUI-TostAI",
|
||||
@ -21248,6 +21278,16 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "Node for Cartesia Sonic-3 that calls the `/tts/bytes` endpoint and returns: file_path, bytes, url"
|
||||
},
|
||||
{
|
||||
"author": "PauldeLavallaz",
|
||||
"title": "[WIP] comfyui_morpheus_model_management",
|
||||
"reference": "https://github.com/PauldeLavallaz/comfyui_morpheus_model_management",
|
||||
"files": [
|
||||
"https://github.com/PauldeLavallaz/comfyui_morpheus_model_management"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Nodo personalizzato per ComfyUI che consente di sfogliare una libreria locale di immagini di talent con interfaccia gallery, filtri avanzati e output multipli. (Description by CC)\nNOTE: The files in the repo are not organized."
|
||||
},
|
||||
{
|
||||
"author": "huanngzh",
|
||||
"title": "ComfyUI-MVAdapter",
|
||||
@ -24748,6 +24788,16 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "This repository contains custom nodes for Stability AI API which supports SD3.0 and 3.5."
|
||||
},
|
||||
{
|
||||
"author": "aicuai",
|
||||
"title": "comfyui-save-image-watermark",
|
||||
"reference": "https://github.com/aicuai/comfyui-save-image-watermark",
|
||||
"files": [
|
||||
"https://github.com/aicuai/comfyui-save-image-watermark"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Save images with visible watermarks (logo/text), invisible watermarks (LSB steganography), and metadata embedding. Supports PNG/JPEG/WebP with browser download."
|
||||
},
|
||||
{
|
||||
"author": "benda1989",
|
||||
"title": "GKK·CosyVoice",
|
||||
@ -37592,16 +37642,6 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "Color match nodes for ComfyUI that color-match target images against reference images with manual or auto-ramped blending, ideal for smooth color transitions between video clips."
|
||||
},
|
||||
{
|
||||
"author": "Wladimir Palant",
|
||||
"title": "image-resize-comfyui",
|
||||
"reference": "https://github.com/ussoewwin/image_resize_comfyui",
|
||||
"files": [
|
||||
"https://github.com/ussoewwin/image_resize_comfyui"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Advanced image resizing node for ComfyUI with aspect ratio preservation and mask support"
|
||||
},
|
||||
{
|
||||
"author": "jianghong-zhu",
|
||||
"title": "ComfyUI-AdvancedCameraPrompts",
|
||||
@ -40275,6 +40315,16 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI custom node: load an MP4 and output first/last frame as IMAGE."
|
||||
},
|
||||
{
|
||||
"author": "esp-dev",
|
||||
"title": "comfyui-loadheicimage",
|
||||
"reference": "https://github.com/esp-dev/comfyui-loadheicimage",
|
||||
"files": [
|
||||
"https://github.com/esp-dev/comfyui-loadheicimage"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI custom node that loads images (including HEIC/HEIF) and provides browser-friendly previews."
|
||||
},
|
||||
{
|
||||
"author": "mudknight",
|
||||
"title": "comfyui-mudknight-utils",
|
||||
@ -40316,16 +40366,6 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "A ComfyUI node that generates a VACE control video and mask for a smooth transition between two videos"
|
||||
},
|
||||
{
|
||||
"author": "WASasquatch",
|
||||
"title": "ComfyUI_Viewer",
|
||||
"reference": "https://github.com/WASasquatch/ComfyUI_Viewer",
|
||||
"files": [
|
||||
"https://github.com/WASasquatch/ComfyUI_Viewer"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Extensible content viewer for ComfyUI: HTML, Markdown (LaTeX, Mermaid, etc), Code, Images, and more"
|
||||
},
|
||||
{
|
||||
"author": "Xyc2016",
|
||||
"title": "Comfyui_Fd_Nodes",
|
||||
@ -40446,16 +40486,6 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "A minimal, opinionated ComfyUI custom node that emits portrait (0°) and/or landscape (90°) latent variants in a single run."
|
||||
},
|
||||
{
|
||||
"author": "alexcong",
|
||||
"title": "ComfyUI-SwinIR",
|
||||
"reference": "https://github.com/alexcong/ComfyUI-SwinIR",
|
||||
"files": [
|
||||
"https://github.com/alexcong/ComfyUI-SwinIR"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A ComfyUI custom node for SwinIR (Swin Transformer for Image Restoration) supporting image super-resolution and denoising."
|
||||
},
|
||||
{
|
||||
"author": "zisb",
|
||||
"title": "comfyui-texture-packer",
|
||||
@ -41097,6 +41127,16 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "Lightweight post-processing node for Qwen3-4B conditioning in Z-Image Turbo workflows that refines conditioning with per-token normalization, optional self-attention, and MLP refinement. (Description by CC)"
|
||||
},
|
||||
{
|
||||
"author": "capitan01R",
|
||||
"title": "ComfyUI-CapitanZiT-Scheduler",
|
||||
"reference": "https://github.com/capitan01R/ComfyUI-CapitanZiT-Scheduler",
|
||||
"files": [
|
||||
"https://github.com/capitan01R/ComfyUI-CapitanZiT-Scheduler"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A lightweight ComfyUI custom scheduler & sigma generator for Z-Image-Turbo. Delivers a stable linear sigma schedule (1.0 → 0.0) for rectified-flow/flow-matching, boosting few-step generation (8-9 steps) with superior consistency, reduced noise, and full compatibility with the model's distilled pipeline."
|
||||
},
|
||||
{
|
||||
"author": "advancedtech-sk",
|
||||
"title": "ComfyUI-GROUT",
|
||||
@ -41127,16 +41167,6 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "Automatically disables Load Image nodes without images, useful for workflows with optional reference images. (Description by CC)"
|
||||
},
|
||||
{
|
||||
"author": "Enferlain",
|
||||
"title": "ComfyUI-A1111-cond",
|
||||
"reference": "https://github.com/Enferlain/ComfyUI-A1111-cond",
|
||||
"files": [
|
||||
"https://github.com/Enferlain/ComfyUI-A1111-cond"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A custom ComfyUI node that implements A1111-style prompt handling with proper isolation and emphasis math."
|
||||
},
|
||||
{
|
||||
"author": "NickPittas",
|
||||
"title": "ComfyUI_CameraAngleSelector",
|
||||
@ -41167,6 +41197,16 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "A dedicated ComfyUI custom node designed to streamline the process of converting transparent images (RGBA) into masks and high-quality mask previews."
|
||||
},
|
||||
{
|
||||
"author": "tackcrypto1031",
|
||||
"title": "tk_comfyui_view_and_light",
|
||||
"reference": "https://github.com/tackcrypto1031/tk_comfyui_view_and_light",
|
||||
"files": [
|
||||
"https://github.com/tackcrypto1031/tk_comfyui_view_and_light"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "TK View and Light: A ComfyUI node for 3D camera and lighting control"
|
||||
},
|
||||
{
|
||||
"author": "patientx",
|
||||
"title": "CFZ-SwitchMenu",
|
||||
@ -41238,8 +41278,208 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "Provide a simple interface to simplify prompt writing."
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"author": "Suzu008",
|
||||
"title": "ComfyUI-CryptIO",
|
||||
"reference": "https://github.com/Suzu008/ComfyUI-CryptIO",
|
||||
"files": [
|
||||
"https://github.com/Suzu008/ComfyUI-CryptIO"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A collection of custom nodes for ComfyUI"
|
||||
},
|
||||
{
|
||||
"author": "IRCSS",
|
||||
"title": "comfyUI-blender-wrapper",
|
||||
"reference": "https://github.com/IRCSS/comfyUI-blender-wrapper",
|
||||
"files": [
|
||||
"https://github.com/IRCSS/comfyUI-blender-wrapper"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI Blender Wrapper lets you call Blender in headless mode from ComfyUI (or any Python environment), run reusable pipeline stages stored inside files, and pass configs in/out via JSON. It's meant for tech-art / asset-pipeline tasks like cleanup, decimation, unwrap, baking, rigging, etc."
|
||||
},
|
||||
{
|
||||
"author": "calibancode",
|
||||
"title": "ComfyUI-bevvy",
|
||||
"reference": "https://github.com/calibancode/ComfyUI-bevvy",
|
||||
"files": [
|
||||
"https://github.com/calibancode/ComfyUI-bevvy"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI custom node that saves images as WebP."
|
||||
},
|
||||
{
|
||||
"author": "joe002",
|
||||
"title": "comfyui-deterministic-nodes",
|
||||
"reference": "https://github.com/joe002/comfyui-deterministic-nodes",
|
||||
"files": [
|
||||
"https://github.com/joe002/comfyui-deterministic-nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Batch-invariant inference nodes for guaranteed reproducibility in ComfyUI"
|
||||
},
|
||||
{
|
||||
"author": "joe002",
|
||||
"title": "comfyui-conduit-optimizer",
|
||||
"reference": "https://github.com/joe002/comfyui-conduit-optimizer",
|
||||
"files": [
|
||||
"https://github.com/joe002/comfyui-conduit-optimizer"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Non-linear inference optimization for ComfyUI: 4-tier VRAM, speculative generation, precision routing"
|
||||
},
|
||||
{
|
||||
"author": "joe002",
|
||||
"title": "comfyui-rtx4090-nodes",
|
||||
"reference": "https://github.com/joe002/comfyui-rtx4090-nodes",
|
||||
"files": [
|
||||
"https://github.com/joe002/comfyui-rtx4090-nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "High-performance ComfyUI nodes optimized for RTX 4090: batch processing, memory management, GPU monitoring"
|
||||
},
|
||||
{
|
||||
"author": "aadityamundhalia",
|
||||
"title": "ComfyUI-ollama-aditya",
|
||||
"reference": "https://github.com/aadityamundhalia/ComfyUI-ollama-aditya",
|
||||
"files": [
|
||||
"https://github.com/aadityamundhalia/ComfyUI-ollama-aditya"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom ComfyUI node for integrating Ollama LLMs into your image generation workflows."
|
||||
},
|
||||
{
|
||||
"author": "maximilianwicen",
|
||||
"title": "ComfyUI-MaxTools",
|
||||
"reference": "https://github.com/maximilianwicen/ComfyUI-MaxTools",
|
||||
"files": [
|
||||
"https://github.com/maximilianwicen/ComfyUI-MaxTools"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A small collection of custom nodes for ComfyUI, featuring Max Quick Image Size node for image-to-image or image-to-video workflows. (Description by CC)"
|
||||
},
|
||||
{
|
||||
"author": "bhhtr12",
|
||||
"title": "ComfyUI-ollama-stop",
|
||||
"reference": "https://github.com/bhhtr12/ComfyUI-ollama-stop",
|
||||
"files": [
|
||||
"https://github.com/bhhtr12/ComfyUI-ollama-stop"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Passthrough node that instantly unloads any running ollama model mid workflow. No API calls, just accepts plain string as a model name and executes 'ollama stop <model>' command in your system."
|
||||
},
|
||||
{
|
||||
"author": "DemonAlone",
|
||||
"title": "SimpeStringGenerator_ComfyUI",
|
||||
"reference": "https://github.com/DemonAlone/SimpeStringGenerator_ComfyUI",
|
||||
"files": [
|
||||
"https://github.com/DemonAlone/SimpeStringGenerator_ComfyUI"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A collection of nodes that provide dynamic dropdown selectors for Samplers, Schedulers, Checkpoints, and Diffusion Models, outputting a comma-separated string for use in XY plots."
|
||||
},
|
||||
{
|
||||
"author": "tabisheva",
|
||||
"title": "comfyui-segs-profile",
|
||||
"reference": "https://github.com/tabisheva/comfyui-segs-profile",
|
||||
"files": [
|
||||
"https://github.com/tabisheva/comfyui-segs-profile"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A tiny ComfyUI custom node that detects whether a face is in profile using SEGS eye detections."
|
||||
},
|
||||
{
|
||||
"author": "QuackPhuc",
|
||||
"title": "ComfyUI-FisheyeTransform",
|
||||
"reference": "https://github.com/QuackPhuc/ComfyUI-FisheyeTransform",
|
||||
"files": [
|
||||
"https://github.com/QuackPhuc/ComfyUI-FisheyeTransform"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom nodes for handling fisheye camera distortion in ComfyUI inpainting workflows."
|
||||
},
|
||||
{
|
||||
"author": "1x1r",
|
||||
"title": "comfyui-upscale-by-model",
|
||||
"reference": "https://github.com/1x1r/comfyui-upscale-by-model",
|
||||
"files": [
|
||||
"https://github.com/1x1r/comfyui-upscale-by-model"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "This custom node allow upscaling an image by a factor using a model."
|
||||
},
|
||||
{
|
||||
"author": "XelaNull",
|
||||
"title": "ComfyUI-MobileFriendly",
|
||||
"reference": "https://github.com/XelaNull/ComfyUI-MobileFriendly",
|
||||
"files": [
|
||||
"https://github.com/XelaNull/ComfyUI-MobileFriendly"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Comprehensive mobile UI enhancement for ComfyUI that transforms the desktop-focused interface into a touch-friendly experience optimized for iPhone, iPad, and Android devices."
|
||||
},
|
||||
{
|
||||
"author": "danieljanata",
|
||||
"title": "ComfyUI-Prompting-System",
|
||||
"reference": "https://github.com/danieljanata/ComfyUI-Prompting-System",
|
||||
"files": [
|
||||
"https://github.com/danieljanata/ComfyUI-Prompting-System"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Comprehensive prompt management system for ComfyUI with database storage, thumbnail management, advanced search, and cross-platform support."
|
||||
},
|
||||
{
|
||||
"author": "SorenWeile",
|
||||
"title": "ComfyUI_MetaSaver",
|
||||
"reference": "https://github.com/SorenWeile/ComfyUI_MetaSaver",
|
||||
"files": [
|
||||
"https://github.com/SorenWeile/ComfyUI_MetaSaver"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A powerful ComfyUI custom node for saving images with flexible custom metadata fields embedded in PNG files."
|
||||
},
|
||||
{
|
||||
"author": "theluminhub",
|
||||
"title": "ComfyUI-Lumin-Upload",
|
||||
"reference": "https://github.com/theluminhub/ComfyUI-Lumin-Upload",
|
||||
"files": [
|
||||
"https://github.com/theluminhub/ComfyUI-Lumin-Upload"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Upload your ComfyUI generated images and workflow metadata to Lumin."
|
||||
},
|
||||
{
|
||||
"author": "RCAKangle",
|
||||
"title": "ComfyUI_LLM_Embeder",
|
||||
"reference": "https://github.com/RCAKangle/ComfyUI_LLM_Embeder",
|
||||
"files": [
|
||||
"https://github.com/RCAKangle/ComfyUI_LLM_Embeder"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Local LLM chat nodes for ComfyUI, with a clean handoff path to downstream prompt optimization."
|
||||
},
|
||||
{
|
||||
"author": "loz2754",
|
||||
"title": "AUN ComfyUI Nodes",
|
||||
"id": "aun-comfyui-nodes",
|
||||
"reference": "https://github.com/loz2754/AUN-ComfyUI-Nodes",
|
||||
"files": [
|
||||
"https://github.com/loz2754/AUN-ComfyUI-Nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A collection of workflow helper nodes focused on organization + control (bypass/mute/collapse/group control), prompt/text utilities, file/path helpers, and image/video save helpers (optional VHS integration)."
|
||||
},
|
||||
{
|
||||
"author": "SergPoletaev",
|
||||
"title": "ComfyUI-SPoletNodes",
|
||||
"id": "ComfyUI-SPoletNodes",
|
||||
"reference": "https://github.com/SergPoletaev/ComfyUI-SPoletNodes",
|
||||
"files": [
|
||||
"https://github.com/SergPoletaev/ComfyUI-SPoletNodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom nodes for image preview and saving"
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
],
|
||||
"https://github.com/0nikod/ComfyUI-Simple-Prompt": [
|
||||
[
|
||||
"vue-basic"
|
||||
"SimplePrompt"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-Simple-Prompt"
|
||||
@ -507,6 +507,14 @@
|
||||
"title_aux": "Comfyui-Gelbooru"
|
||||
}
|
||||
],
|
||||
"https://github.com/1x1r/comfyui-upscale-by-model": [
|
||||
[
|
||||
"UpscaleImageByUsingModel"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-upscale-by-model"
|
||||
}
|
||||
],
|
||||
"https://github.com/1zhangyy1/comfyui-vidu-nodes": [
|
||||
[
|
||||
"Character2Video",
|
||||
@ -587,8 +595,8 @@
|
||||
],
|
||||
"https://github.com/3R3BOS/ComfyUI-3R3BOS-Pack": [
|
||||
[
|
||||
"Image Comparer (3R3BOS)",
|
||||
"Visual Gatekeeper (3R3BOS)"
|
||||
"Batch Selector (3R3BOS)",
|
||||
"Image Comparer (3R3BOS)"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-3R3BOS-Pack"
|
||||
@ -2730,7 +2738,8 @@
|
||||
],
|
||||
"https://github.com/Anzhc/SDXL-Flux2VAE-ComfyUI-Node": [
|
||||
[
|
||||
"EmptySDXLFlux2LatentImage"
|
||||
"EmptySDXLFlux2LatentImage",
|
||||
"TargetTimeConditioning"
|
||||
],
|
||||
{
|
||||
"title_aux": "SDXL-Flux2VAE-ComfyUI-Node"
|
||||
@ -5963,6 +5972,17 @@
|
||||
"title_aux": "RangeToString"
|
||||
}
|
||||
],
|
||||
"https://github.com/DemonAlone/SimpeStringGenerator_ComfyUI": [
|
||||
[
|
||||
"DiffusionModelGeneratorNode",
|
||||
"ModelGeneratorNode",
|
||||
"SamplerGeneratorNode",
|
||||
"SchedulerGeneratorNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "SimpeStringGenerator_ComfyUI"
|
||||
}
|
||||
],
|
||||
"https://github.com/DemonNCoding/PromptGenerator12Columns": [
|
||||
[
|
||||
"PromptGenerator12Columns_Empty",
|
||||
@ -8718,6 +8738,14 @@
|
||||
"title_aux": "ComfyUI Visual Dimension Selector"
|
||||
}
|
||||
],
|
||||
"https://github.com/GraftingRayman/ComfyUI-Games": [
|
||||
[
|
||||
"TetrisNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-Games"
|
||||
}
|
||||
],
|
||||
"https://github.com/GraftingRayman/ComfyUI-PuLID-Flux-GR": [
|
||||
[
|
||||
"GRApplyPulidFlux",
|
||||
@ -8774,7 +8802,7 @@
|
||||
"GR Text Overlay",
|
||||
"GR Tile and Border Image",
|
||||
"GR Tile and Border Image Random Flip",
|
||||
"GRBatchLoader",
|
||||
"GRAudioSelector",
|
||||
"GRImageSelector",
|
||||
"GRLoraLoader",
|
||||
"GRMenuHook",
|
||||
@ -10021,6 +10049,49 @@
|
||||
"title_aux": "Notification Bridge"
|
||||
}
|
||||
],
|
||||
"https://github.com/IRCSS/comfyUI-blender-wrapper": [
|
||||
[
|
||||
"BlenderGenericNode",
|
||||
"CV2InpaintTexture",
|
||||
"DownloadAndLoadHy3DDelightModel",
|
||||
"DownloadAndLoadHy3DPaintModel",
|
||||
"Hy3DApplyTexture",
|
||||
"Hy3DBPT",
|
||||
"Hy3DBakeFromMultiview",
|
||||
"Hy3DCameraConfig",
|
||||
"Hy3DDelightImage",
|
||||
"Hy3DDiffusersSchedulerConfig",
|
||||
"Hy3DExportMesh",
|
||||
"Hy3DFastSimplifyMesh",
|
||||
"Hy3DGenerateMesh",
|
||||
"Hy3DGenerateMeshMultiView",
|
||||
"Hy3DGetMeshPBRTextures",
|
||||
"Hy3DIMRemesh",
|
||||
"Hy3DLoadMesh",
|
||||
"Hy3DMeshInfo",
|
||||
"Hy3DMeshUVWrap",
|
||||
"Hy3DMeshVerticeInpaintTexture",
|
||||
"Hy3DModelLoader",
|
||||
"Hy3DNvdiffrastRenderer",
|
||||
"Hy3DPostprocessMesh",
|
||||
"Hy3DRenderMultiView",
|
||||
"Hy3DRenderMultiViewDepth",
|
||||
"Hy3DRenderSingleView",
|
||||
"Hy3DSampleMultiView",
|
||||
"Hy3DSetMeshPBRAttributes",
|
||||
"Hy3DSetMeshPBRTextures",
|
||||
"Hy3DTorchCompileSettings",
|
||||
"Hy3DUploadMesh",
|
||||
"Hy3DVAEDecode",
|
||||
"Hy3DVAELoader",
|
||||
"Hy3D_2_1SimpleMeshGen",
|
||||
"MESHToTrimesh",
|
||||
"TrimeshToMESH"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyUI-blender-wrapper"
|
||||
}
|
||||
],
|
||||
"https://github.com/ITurchenko/ComfyUI-SizeFromArray": [
|
||||
[
|
||||
"SizeFromArray"
|
||||
@ -13032,6 +13103,20 @@
|
||||
"title_aux": "comfyui-vram-overlay"
|
||||
}
|
||||
],
|
||||
"https://github.com/MajoorWaldi/ComfyUI-Majoor-ImageOps": [
|
||||
[
|
||||
"ImageOpsBlur",
|
||||
"ImageOpsClamp",
|
||||
"ImageOpsColorAjust",
|
||||
"ImageOpsInvert",
|
||||
"ImageOpsMerge",
|
||||
"ImageOpsPreview",
|
||||
"ImageOpsTransform"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-Majoor-ImageOps"
|
||||
}
|
||||
],
|
||||
"https://github.com/Makeezi/ComfyUI-promptLAB": [
|
||||
[
|
||||
"PromptLAB"
|
||||
@ -13736,11 +13821,13 @@
|
||||
"Remove Background",
|
||||
"ReplaceAlpha",
|
||||
"Resize Image and Mask by Side",
|
||||
"SEGS Normalize for Video",
|
||||
"Save Folder as ZIP",
|
||||
"Save To Zip",
|
||||
"SaveFolderAsZip",
|
||||
"Spritesheet Builder",
|
||||
"Spritesheet Preview",
|
||||
"Stabilizer Trim",
|
||||
"VideoMaskEditor",
|
||||
"WAN Frame Calculator"
|
||||
],
|
||||
@ -15128,6 +15215,14 @@
|
||||
"title_aux": "Claude Prompt Generator"
|
||||
}
|
||||
],
|
||||
"https://github.com/PauldeLavallaz/comfyui_morpheus_model_management": [
|
||||
[
|
||||
"MorpheusModelManagement"
|
||||
],
|
||||
{
|
||||
"title_aux": "[WIP] comfyui_morpheus_model_management"
|
||||
}
|
||||
],
|
||||
"https://github.com/PenguinTeo/Comfyui-GeminiBanana": [
|
||||
[
|
||||
"Gemini3ImageNode"
|
||||
@ -15863,6 +15958,16 @@
|
||||
"title_aux": "ComfyUI-RED-UNO"
|
||||
}
|
||||
],
|
||||
"https://github.com/QuackPhuc/ComfyUI-FisheyeTransform": [
|
||||
[
|
||||
"FisheyeRedistort",
|
||||
"FisheyeStrengthEstimate",
|
||||
"FisheyeUndistort"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-FisheyeTransform"
|
||||
}
|
||||
],
|
||||
"https://github.com/QuietNoise/comfyui_queue_manager": [
|
||||
[
|
||||
"Workflow Name"
|
||||
@ -15879,6 +15984,16 @@
|
||||
"title_aux": "Universal LLM Node for ComfyUI"
|
||||
}
|
||||
],
|
||||
"https://github.com/RCAKangle/ComfyUI_LLM_Embeder": [
|
||||
[
|
||||
"ChatHistoryViewer",
|
||||
"ChatNode",
|
||||
"LLMConfigNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_LLM_Embeder"
|
||||
}
|
||||
],
|
||||
"https://github.com/RUiNtheExtinct/comfyui-save-file-extended": [
|
||||
[
|
||||
"LoadAudioExtended",
|
||||
@ -17291,6 +17406,19 @@
|
||||
"title_aux": "HF-Flux-ComfyUI"
|
||||
}
|
||||
],
|
||||
"https://github.com/SergPoletaev/ComfyUI-SPoletNodes": [
|
||||
[
|
||||
"EnhancedVideoPreview",
|
||||
"GetImageSizeWithPreview",
|
||||
"Save Images & Preview",
|
||||
"UltimateMemoryCleaner",
|
||||
"Video Concat (FFmpeg)",
|
||||
"VideoBatchCrossfade"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-SPoletNodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/ServiceStack/comfy-asset-downloader": [
|
||||
[
|
||||
"AssetDownloader"
|
||||
@ -18171,6 +18299,15 @@
|
||||
"title_aux": "MBM's Music Visualizer"
|
||||
}
|
||||
],
|
||||
"https://github.com/SorenWeile/ComfyUI_MetaSaver": [
|
||||
[
|
||||
"MetaSaver",
|
||||
"MetaSaverDynamic"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_MetaSaver"
|
||||
}
|
||||
],
|
||||
"https://github.com/SozeInc/ComfyUI-Mobile": [
|
||||
[
|
||||
"Send Notification (Mobile)",
|
||||
@ -18712,6 +18849,7 @@
|
||||
"Basic data handling: TimeExtract",
|
||||
"Basic data handling: TimeFormat",
|
||||
"Basic data handling: TimeNow",
|
||||
"Basic data handling: TimeNowUTC",
|
||||
"Basic data handling: TimeParse",
|
||||
"Basic data handling: TimeSubtractDelta",
|
||||
"Basic data handling: TimeToUnix",
|
||||
@ -19233,6 +19371,21 @@
|
||||
"title_aux": "Comfyroll Studio"
|
||||
}
|
||||
],
|
||||
"https://github.com/Suzu008/ComfyUI-CryptIO": [
|
||||
[
|
||||
"PreviewImageCryptIO",
|
||||
"PreviewVideoCryptIO",
|
||||
"SaveImageCryptIO",
|
||||
"SaveVideoCryptIO",
|
||||
"TextDecrypt",
|
||||
"TextEncrypt",
|
||||
"UploadImageCryptIO",
|
||||
"UploadVideoCryptIO"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-CryptIO"
|
||||
}
|
||||
],
|
||||
"https://github.com/SuzumiyaAkizuki/ComfyUI-LLM_Prompt_XML_Formatter": [
|
||||
[
|
||||
"LLM_Prompt_Formatter",
|
||||
@ -19521,6 +19674,17 @@
|
||||
"title_aux": "tri3d-comfyui-nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/TTPlanetPig/Comfyui_DreamID-V_wrapper": [
|
||||
[
|
||||
"DreamIDV_ConditioningPrep_TTP",
|
||||
"DreamIDV_ModelLoader_Wrapper_TTP",
|
||||
"DreamIDV_PoseExtractor_TTP",
|
||||
"DreamIDV_Sampler_Wrapper_TTP"
|
||||
],
|
||||
{
|
||||
"title_aux": "Comfyui_DreamID-V_wrapper"
|
||||
}
|
||||
],
|
||||
"https://github.com/TTPlanetPig/Comfyui_Hunyuan3D": [
|
||||
[
|
||||
"GifImageViewerNode",
|
||||
@ -20083,6 +20247,8 @@
|
||||
[
|
||||
"CharacterLoraSelect",
|
||||
"ChromaActionSelect",
|
||||
"EasyArrayFilter",
|
||||
"EasyBasicJsonExtractor",
|
||||
"EasyCLIPLoader",
|
||||
"EasyCheckpointLoader",
|
||||
"EasyFileName",
|
||||
@ -20100,6 +20266,8 @@
|
||||
"LoadImagesFromDirectoryPath",
|
||||
"LoadRandomImageFromFolderPath",
|
||||
"QwenActionSelect",
|
||||
"TileAssembly",
|
||||
"TileBreak",
|
||||
"UserSelect",
|
||||
"WanActionSelect"
|
||||
],
|
||||
@ -22485,6 +22653,14 @@
|
||||
"title_aux": "ComfyUI_Detonate"
|
||||
}
|
||||
],
|
||||
"https://github.com/aadityamundhalia/ComfyUI-ollama-aditya": [
|
||||
[
|
||||
"OllamaPromptGenerator"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-ollama-aditya"
|
||||
}
|
||||
],
|
||||
"https://github.com/abdozmantar/ComfyUI-DeepExtract": [
|
||||
[
|
||||
"VocalAndSoundRemoverNode"
|
||||
@ -22948,6 +23124,16 @@
|
||||
"title_aux": "aicu-comfyui-stability-ai-api"
|
||||
}
|
||||
],
|
||||
"https://github.com/aicuai/comfyui-save-image-watermark": [
|
||||
[
|
||||
"ExtractInvisibleWatermark",
|
||||
"Local Save",
|
||||
"LocalSaveImageWithWatermark"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-save-image-watermark"
|
||||
}
|
||||
],
|
||||
"https://github.com/aidec/Comfyui_TextBatch_aidec": [
|
||||
[
|
||||
"DataTempManager",
|
||||
@ -23232,7 +23418,6 @@
|
||||
"GetImagesFromBatchIndexed",
|
||||
"GetLatentRangeFromBatch",
|
||||
"GetLatentSizeAndCount",
|
||||
"Image Comparer (rgthree)",
|
||||
"ImageAddMulti",
|
||||
"ImageAndMaskPreview",
|
||||
"ImageBatchExtendWithOverlap",
|
||||
@ -23257,6 +23442,7 @@
|
||||
"ImagePadKJ",
|
||||
"ImagePass",
|
||||
"ImagePrepForICLora",
|
||||
"ImageResizeByMegapixels",
|
||||
"ImageResizeKJ",
|
||||
"ImageResizeKJv2",
|
||||
"ImageTensorList",
|
||||
@ -23275,6 +23461,7 @@
|
||||
"LoadImagesFromFolderKJ",
|
||||
"LoadVideosFromFolder",
|
||||
"Mask_transform_sum",
|
||||
"MathExpression_UTK",
|
||||
"MergeBatch",
|
||||
"MergeImageChannels",
|
||||
"PadImageBatchInterleaved",
|
||||
@ -23587,6 +23774,8 @@
|
||||
"GeminiConvertRasterToVector",
|
||||
"GeminiFLUXResolutions",
|
||||
"GeminiImageGenerator",
|
||||
"GeminiLoadImagePath",
|
||||
"GeminiLoadImagesFromDir",
|
||||
"GeminiSVGPreview",
|
||||
"GeminiSaveSVG",
|
||||
"GeminiSaveText",
|
||||
@ -23894,10 +24083,15 @@
|
||||
"XJSamplerAdapter",
|
||||
"XJSaveImageWithMetadata",
|
||||
"XJSchedulerAdapter",
|
||||
"XJSegsAutoAdjustHookProvider",
|
||||
"XJSegsColorCorrectHSVHookProvider",
|
||||
"XJSegsColorCorrectRGBHookProvider",
|
||||
"XJSegsColorMatchHookProvider",
|
||||
"XJSegsCount",
|
||||
"XJSegsExtractor",
|
||||
"XJSegsFilter",
|
||||
"XJSegsFilterByLabel",
|
||||
"XJSegsMerge",
|
||||
"XJSegsPick",
|
||||
"XJSegsStitcher",
|
||||
"XJSegsWildcardPrompt",
|
||||
@ -25593,6 +25787,14 @@
|
||||
"title_aux": "ComfyUI-Hunyuan-Image-3"
|
||||
}
|
||||
],
|
||||
"https://github.com/bhhtr12/ComfyUI-ollama-stop": [
|
||||
[
|
||||
"OllamaStopNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-ollama-stop"
|
||||
}
|
||||
],
|
||||
"https://github.com/bhvbhushan/ComfyUI-LoRABlockWeight": [
|
||||
[
|
||||
"HierarchicalLoRAWeightEditor",
|
||||
@ -26861,6 +27063,14 @@
|
||||
"title_aux": "Arc2Face ComfyUI Node Library"
|
||||
}
|
||||
],
|
||||
"https://github.com/calibancode/ComfyUI-bevvy": [
|
||||
[
|
||||
"SaveImageWebP"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-bevvy"
|
||||
}
|
||||
],
|
||||
"https://github.com/camenduru/ComfyUI-TostAI": [
|
||||
[
|
||||
"SendToTostAI"
|
||||
@ -26878,6 +27088,14 @@
|
||||
"title_aux": "Capitan-ConditioningEnhancer"
|
||||
}
|
||||
],
|
||||
"https://github.com/capitan01R/ComfyUI-CapitanZiT-Scheduler": [
|
||||
[
|
||||
"CapitanZiTLinearSigma"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-CapitanZiT-Scheduler"
|
||||
}
|
||||
],
|
||||
"https://github.com/cardenluo/ComfyUI-Apt_Preset": [
|
||||
[
|
||||
"AD_DrawSchedule",
|
||||
@ -26897,6 +27115,8 @@
|
||||
"AD_sch_value",
|
||||
"AD_slice_Condi",
|
||||
"AI_GLM4",
|
||||
"AI_GLM_image",
|
||||
"AI_GLM_text",
|
||||
"AI_Ollama_image",
|
||||
"AI_Ollama_text",
|
||||
"AI_PresetSave",
|
||||
@ -27187,7 +27407,6 @@
|
||||
"sum_lora",
|
||||
"sum_stack_AD",
|
||||
"sum_stack_Kontext",
|
||||
"sum_stack_QwenEdit",
|
||||
"sum_stack_QwenEditPlus",
|
||||
"sum_stack_Wan",
|
||||
"sum_stack_image",
|
||||
@ -29566,6 +29785,13 @@
|
||||
"MaskComposite",
|
||||
"MaskPreview",
|
||||
"MaskToImage",
|
||||
"MeshyAnimateModelNode",
|
||||
"MeshyImageToModelNode",
|
||||
"MeshyMultiImageToModelNode",
|
||||
"MeshyRefineNode",
|
||||
"MeshyRigModelNode",
|
||||
"MeshyTextToModelNode",
|
||||
"MeshyTextureNode",
|
||||
"MinimaxHailuoVideoNode",
|
||||
"MinimaxImageToVideoNode",
|
||||
"MinimaxSubjectToVideoNode",
|
||||
@ -30753,6 +30979,17 @@
|
||||
"title_aux": "ComfyUI-TTS"
|
||||
}
|
||||
],
|
||||
"https://github.com/danieljanata/ComfyUI-Prompting-System": [
|
||||
[
|
||||
"PS_MetadataCleaner",
|
||||
"PS_MetadataReader",
|
||||
"PS_PromptSaver",
|
||||
"PS_SmartText"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-Prompting-System"
|
||||
}
|
||||
],
|
||||
"https://github.com/danielvw/ComfyUI-WanMove-Adapter": [
|
||||
[
|
||||
"CoordsToWanTracks"
|
||||
@ -30924,6 +31161,7 @@
|
||||
"PromptCameraSelector",
|
||||
"PromptConstructor",
|
||||
"PromptLightingSelector",
|
||||
"Test1",
|
||||
"TiledKSampler",
|
||||
"TiledKSamplerWithUpscaler",
|
||||
"TrainingDatasetSaver"
|
||||
@ -32348,6 +32586,14 @@
|
||||
"title_aux": "ComfyUI-enricos-nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/esp-dev/comfyui-loadheicimage": [
|
||||
[
|
||||
"LoadImagePlusHEIC"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-loadheicimage"
|
||||
}
|
||||
],
|
||||
"https://github.com/esp-dev/comfyui-videoframenode": [
|
||||
[
|
||||
"VideoFirstLastFrame"
|
||||
@ -37581,6 +37827,51 @@
|
||||
"title_aux": "HouseKeeper"
|
||||
}
|
||||
],
|
||||
"https://github.com/joe002/comfyui-conduit-optimizer": [
|
||||
[
|
||||
"ConduitApply",
|
||||
"ConduitBatchOptimizer",
|
||||
"ConduitCacheClear",
|
||||
"ConduitCore",
|
||||
"ConduitEmbeddingCache",
|
||||
"ConduitGate",
|
||||
"ConduitLatentCache",
|
||||
"ConduitPath",
|
||||
"ConduitPool",
|
||||
"ConduitPrecisionPatcher",
|
||||
"ConduitSeal",
|
||||
"ConduitSense",
|
||||
"ConduitSpeculativeKSampler"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-conduit-optimizer"
|
||||
}
|
||||
],
|
||||
"https://github.com/joe002/comfyui-deterministic-nodes": [
|
||||
[
|
||||
"CascadeRefiner",
|
||||
"ChecksumValidator",
|
||||
"DeterministicSampler",
|
||||
"ECHOContextNode",
|
||||
"MoERouterNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-deterministic-nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/joe002/comfyui-rtx4090-nodes": [
|
||||
[
|
||||
"BatchImageProcessor",
|
||||
"BatchLatentProcessor",
|
||||
"GPUMonitor",
|
||||
"MemoryManager",
|
||||
"RTX4090Optimizer",
|
||||
"TensorRTAutoConverter"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-rtx4090-nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/joeriben/ai4artsed_comfyui_nodes": [
|
||||
[
|
||||
"ai4artsed_conditioning_fusion",
|
||||
@ -41670,6 +41961,81 @@
|
||||
"title_aux": "ComfyUI-Replace-First-Frame-Last-Frame"
|
||||
}
|
||||
],
|
||||
"https://github.com/loz2754/AUN-ComfyUI-Nodes": [
|
||||
[
|
||||
"AUNAddToPrompt",
|
||||
"AUNAny",
|
||||
"AUNBookmark",
|
||||
"AUNBoolean",
|
||||
"AUNCFG",
|
||||
"AUNCheckpointLoaderWithClipSkip",
|
||||
"AUNEmptyLatent",
|
||||
"AUNExtractModelName",
|
||||
"AUNExtractPowerLoras",
|
||||
"AUNExtractWidgetValue",
|
||||
"AUNGetActiveNodeTitle",
|
||||
"AUNGetConnectedNodeTitles",
|
||||
"AUNGraphScraper",
|
||||
"AUNImageLoadResize",
|
||||
"AUNImageResize",
|
||||
"AUNImageSingleBatch3",
|
||||
"AUNImg2Img",
|
||||
"AUNImgLoader",
|
||||
"AUNInputs",
|
||||
"AUNInputsHybrid",
|
||||
"AUNKSamplerPlusv3",
|
||||
"AUNModelNamePass",
|
||||
"AUNModelShorten",
|
||||
"AUNMultiBypassIndex",
|
||||
"AUNMultiGroupUniversal",
|
||||
"AUNMultiMuteIndex",
|
||||
"AUNMultiNegPrompt",
|
||||
"AUNMultiUniversal",
|
||||
"AUNNameCrop",
|
||||
"AUNNodeStateController",
|
||||
"AUNPathFilename",
|
||||
"AUNPathFilenameVideo",
|
||||
"AUNRandomAnySwitch",
|
||||
"AUNRandomIndexSwitch",
|
||||
"AUNRandomNumber",
|
||||
"AUNRandomTextIndexSwitch",
|
||||
"AUNSaveImage",
|
||||
"AUNSaveVideo",
|
||||
"AUNSetBypassByTitle",
|
||||
"AUNSetBypassStateGroup",
|
||||
"AUNSetCollapseAndBypassStateAdvanced",
|
||||
"AUNSetMuteByTitle",
|
||||
"AUNSetMuteStateGroup",
|
||||
"AUNShowTextWithTitle",
|
||||
"AUNSingleLabelSwitch",
|
||||
"AUNStrip",
|
||||
"AUNSwitchFloat",
|
||||
"AUNTextIndexSwitch",
|
||||
"AUNTextIndexSwitch3",
|
||||
"AUNTitleImagePreview",
|
||||
"AnyType(str)",
|
||||
"AudioInputOptions",
|
||||
"JNodes_AnyToString",
|
||||
"JNodes_ConditioningInOut",
|
||||
"JNodes_FloatLiteral",
|
||||
"JNodes_GetCleanFilename",
|
||||
"JNodes_GetComfyDirectory",
|
||||
"JNodes_GetLeafDirectory",
|
||||
"JNodes_GetOutputDirectory",
|
||||
"JNodes_GetTempDirectory",
|
||||
"JNodes_IntLiteral",
|
||||
"JNodes_ModelInOut",
|
||||
"JNodes_StringLiteral",
|
||||
"JNodes_SubdirectorySelector",
|
||||
"JoinVideosInDirectory",
|
||||
"KSamplerInputs",
|
||||
"MainFolderManualName",
|
||||
"TextSwitch2InputWithTextOutput"
|
||||
],
|
||||
{
|
||||
"title_aux": "AUN ComfyUI Nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/lquesada/ComfyUI-Inpaint-CropAndStitch": [
|
||||
[
|
||||
"InpaintCropImproved",
|
||||
@ -43107,6 +43473,14 @@
|
||||
"title_aux": "comfyui-sora-node"
|
||||
}
|
||||
],
|
||||
"https://github.com/maximilianwicen/ComfyUI-MaxTools": [
|
||||
[
|
||||
"MaxQuickImageSize"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-MaxTools"
|
||||
}
|
||||
],
|
||||
"https://github.com/maxious/comfyui-dap": [
|
||||
[
|
||||
"DAP_ERP_to_Cubemap",
|
||||
@ -45418,6 +45792,57 @@
|
||||
"title_aux": "ComfyUI-HfLoader"
|
||||
}
|
||||
],
|
||||
"https://github.com/olduvai-jp/ComfyUI-S3-IO": [
|
||||
[
|
||||
"LoadImageS3",
|
||||
"LoadVideoUploadS3",
|
||||
"SaveImageS3",
|
||||
"VHS_AudioToVHSAudio",
|
||||
"VHS_BatchManager",
|
||||
"VHS_DuplicateImages",
|
||||
"VHS_DuplicateLatents",
|
||||
"VHS_DuplicateMasks",
|
||||
"VHS_GetImageCount",
|
||||
"VHS_GetLatentCount",
|
||||
"VHS_GetMaskCount",
|
||||
"VHS_LoadAudio",
|
||||
"VHS_LoadAudioUpload",
|
||||
"VHS_LoadImagePath",
|
||||
"VHS_LoadImages",
|
||||
"VHS_LoadImagesPath",
|
||||
"VHS_LoadVideo",
|
||||
"VHS_LoadVideoFFmpeg",
|
||||
"VHS_LoadVideoFFmpegPath",
|
||||
"VHS_LoadVideoPath",
|
||||
"VHS_MergeImages",
|
||||
"VHS_MergeLatents",
|
||||
"VHS_MergeMasks",
|
||||
"VHS_PruneOutputs",
|
||||
"VHS_SelectEveryNthImage",
|
||||
"VHS_SelectEveryNthLatent",
|
||||
"VHS_SelectEveryNthMask",
|
||||
"VHS_SelectFilename",
|
||||
"VHS_SelectImages",
|
||||
"VHS_SelectLatents",
|
||||
"VHS_SelectLatest",
|
||||
"VHS_SelectMasks",
|
||||
"VHS_SplitImages",
|
||||
"VHS_SplitLatents",
|
||||
"VHS_SplitMasks",
|
||||
"VHS_Unbatch",
|
||||
"VHS_VAEDecodeBatched",
|
||||
"VHS_VAEEncodeBatched",
|
||||
"VHS_VHSAudioToAudio",
|
||||
"VHS_VideoCombine",
|
||||
"VHS_VideoInfo",
|
||||
"VHS_VideoInfoLoaded",
|
||||
"VHS_VideoInfoSource",
|
||||
"VideoCombineS3"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-S3-IO"
|
||||
}
|
||||
],
|
||||
"https://github.com/oleksandr612/ComfyUI-Counter": [
|
||||
[
|
||||
"Simple Counter"
|
||||
@ -46611,6 +47036,7 @@
|
||||
"Lora Loader Str",
|
||||
"MaskEmptyFloatNode",
|
||||
"MaskPassOrPlaceholder",
|
||||
"MonoToStereoConverter",
|
||||
"ParametricEQNode",
|
||||
"PonyFaceEnhancementPipelineWithInjection",
|
||||
"PonyUpscaleSamplerWithInjection",
|
||||
@ -49833,6 +50259,7 @@
|
||||
"LoRAExtractKnee",
|
||||
"LoRAExtractQuantile",
|
||||
"LoRAExtractRatio",
|
||||
"LoRAMergeToModel",
|
||||
"LoRAMetaKeys",
|
||||
"LoRAMultiMerge",
|
||||
"LoRAPruneKeys",
|
||||
@ -51922,6 +52349,14 @@
|
||||
"title_aux": "SANA_LOWVRAM"
|
||||
}
|
||||
],
|
||||
"https://github.com/tabisheva/comfyui-segs-profile": [
|
||||
[
|
||||
"SEGSIsProfile"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-segs-profile"
|
||||
}
|
||||
],
|
||||
"https://github.com/tackcrypto1031/tk_comfyui_img2mask": [
|
||||
[
|
||||
"TK_Image2Mask"
|
||||
@ -51930,6 +52365,14 @@
|
||||
"title_aux": "tk_comfyui_img2mask"
|
||||
}
|
||||
],
|
||||
"https://github.com/tackcrypto1031/tk_comfyui_view_and_light": [
|
||||
[
|
||||
"TK_View_And_Light"
|
||||
],
|
||||
{
|
||||
"title_aux": "tk_comfyui_view_and_light"
|
||||
}
|
||||
],
|
||||
"https://github.com/takemetosiberia/ComfyUI-SAMURAI--SAM2-": [
|
||||
[
|
||||
"SAMURAIBoxInputNode",
|
||||
@ -52191,6 +52634,14 @@
|
||||
"title_aux": "Divergent Nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/theluminhub/ComfyUI-Lumin-Upload": [
|
||||
[
|
||||
"AssetManagerNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-Lumin-Upload"
|
||||
}
|
||||
],
|
||||
"https://github.com/theshubzworld/ComfyUI-FaceCalloutNode": [
|
||||
[
|
||||
"FaceCalloutEffect",
|
||||
@ -53270,8 +53721,7 @@
|
||||
"DisTorchPurgeVRAMV2",
|
||||
"MemoryManager",
|
||||
"ModelPatchMemoryCleaner",
|
||||
"PatchSageAttentionDM",
|
||||
"SafeMemoryManager"
|
||||
"PatchSageAttentionDM"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-DistorchMemoryManager"
|
||||
@ -53296,14 +53746,6 @@
|
||||
"title_aux": "ComfyUI-QwenImageLoraLoader"
|
||||
}
|
||||
],
|
||||
"https://github.com/ussoewwin/image_resize_comfyui": [
|
||||
[
|
||||
"ImageResizeAdvanced"
|
||||
],
|
||||
{
|
||||
"title_aux": "image-resize-comfyui"
|
||||
}
|
||||
],
|
||||
"https://github.com/vadimcro/VKRiez-Edge": [
|
||||
[
|
||||
"VKriezEnhancedEdgePreprocessor",
|
||||
@ -54378,23 +54820,15 @@
|
||||
],
|
||||
"https://github.com/willmiao/ComfyUI-Lora-Manager": [
|
||||
[
|
||||
"BasicScheduler",
|
||||
"CFGGuider",
|
||||
"CLIPTextEncode",
|
||||
"DebugMetadata",
|
||||
"KSamplerSelect",
|
||||
"LoraDemoNode",
|
||||
"LoraManagerLoader",
|
||||
"LoraManagerTextLoader",
|
||||
"LoraPoolNode",
|
||||
"LoraRandomizerNode",
|
||||
"LoraStacker",
|
||||
"PromptLoraManager",
|
||||
"SamplerCustomAdvanced",
|
||||
"SaveImageLM",
|
||||
"TSC_EfficientLoader",
|
||||
"TriggerWordToggle",
|
||||
"VAEDecode",
|
||||
"WanVideoLoraSelectFromText",
|
||||
"WanVideoLoraSelectLM"
|
||||
],
|
||||
|
||||
8931
github-stats.json
8931
github-stats.json
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,10 @@ import threading
|
||||
import re
|
||||
import shutil
|
||||
import git
|
||||
import glob
|
||||
import json
|
||||
from datetime import datetime
|
||||
from contextlib import contextmanager
|
||||
|
||||
from server import PromptServer
|
||||
import manager_core as core
|
||||
@ -762,6 +765,86 @@ async def fetch_updates(request):
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return web.Response(status=400)
|
||||
|
||||
@routes.get("/customnode/get_node_types_in_workflows")
|
||||
async def get_node_types_in_workflows(request):
|
||||
try:
|
||||
# get our username from the request header
|
||||
user_id = PromptServer.instance.user_manager.get_request_user_id(request)
|
||||
|
||||
# get the base workflow directory (TODO: figure out if non-standard directories are possible, and how to find them)
|
||||
workflow_files_base_path = os.path.abspath(os.path.join(folder_paths.get_user_directory(), user_id, "workflows"))
|
||||
|
||||
logging.debug(f"workflows base path: {workflow_files_base_path}")
|
||||
|
||||
# workflow directory doesn't actually exist, return 204 (No Content)
|
||||
if not os.path.isdir(workflow_files_base_path):
|
||||
logging.debug("workflows base path doesn't exist - nothing to do...")
|
||||
return web.Response(status=204)
|
||||
|
||||
# get all JSON files under the workflow directory
|
||||
workflow_file_relative_paths: list[str] = glob.glob(pathname="**/*.json", root_dir=workflow_files_base_path, recursive=True)
|
||||
|
||||
logging.debug(f"found the following workflows: {workflow_file_relative_paths}")
|
||||
|
||||
# set up our list of workflow/node-lists
|
||||
workflow_node_mappings: list[dict[str, str | list[str]]] = []
|
||||
|
||||
# iterate over each found JSON file
|
||||
for workflow_file_path in workflow_file_relative_paths:
|
||||
|
||||
try:
|
||||
workflow_file_absolute_path = os.path.abspath(os.path.join(workflow_files_base_path, workflow_file_path))
|
||||
logging.debug(f"starting work on {workflow_file_absolute_path}")
|
||||
# load the JSON file
|
||||
workflow_file_data = json.load(open(workflow_file_absolute_path, "r"))
|
||||
|
||||
# make sure there's a nodes key (otherwise this might not actually be a workflow file)
|
||||
if "nodes" not in workflow_file_data:
|
||||
logging.warning(f"{workflow_file_path} has no 'nodes' key (possibly invalid?) - skipping...")
|
||||
# skip to next file
|
||||
continue
|
||||
|
||||
# now this looks like a valid file, so let's get to work
|
||||
new_mapping = {"workflow_file_name": workflow_file_path}
|
||||
# we can't use an actual set, because you can't use dicts as set members
|
||||
node_set = []
|
||||
|
||||
# iterate over each node in the workflow
|
||||
for node in workflow_file_data["nodes"]:
|
||||
if "id" not in node:
|
||||
logging.warning(f"Found a node with no ID - possibly corrupt/invalid workflow?")
|
||||
continue
|
||||
# if there's no type, throw a warning
|
||||
if "type" not in node:
|
||||
logging.warning(f"Node type not found in {workflow_file_path} for node ID {node['id']}")
|
||||
# skip to next node
|
||||
continue
|
||||
|
||||
node_data_to_return = {"type": node["type"]}
|
||||
if "properties" not in node:
|
||||
logging.warning(f"Node ${node['id']} has no properties field - can't determine cnr_id")
|
||||
else:
|
||||
for property_key in ["cnr_id", "ver"]:
|
||||
if property_key in node["properties"]:
|
||||
node_data_to_return[property_key] = node["properties"][property_key]
|
||||
|
||||
# add it to the list for this workflow
|
||||
if not node_data_to_return in node_set:
|
||||
node_set.append(node_data_to_return)
|
||||
|
||||
# annoyingly, Python can't serialize sets to JSON
|
||||
new_mapping["node_types"] = list(node_set)
|
||||
workflow_node_mappings.append(new_mapping)
|
||||
|
||||
except Exception as e:
|
||||
logging.warning(f"Couldn't open {workflow_file_path}: {e}")
|
||||
|
||||
return web.json_response(workflow_node_mappings, content_type='application/json')
|
||||
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return web.Response(status=500)
|
||||
|
||||
|
||||
@routes.get("/manager/queue/update_all")
|
||||
|
||||
@ -9,6 +9,7 @@ This directory contains the JavaScript frontend implementation for ComfyUI-Manag
|
||||
- **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.
|
||||
- **node-usage-analyzer.js**: Implements the UI for analyzing node usage in workflows.
|
||||
|
||||
## Sharing Components
|
||||
|
||||
@ -46,5 +47,6 @@ The frontend follows a modular component-based architecture:
|
||||
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
|
||||
- **node-usage-analyzer.css**: Styling for the node usage analyzer UI
|
||||
|
||||
This frontend implementation provides a comprehensive yet user-friendly interface for managing the ComfyUI ecosystem.
|
||||
|
||||
@ -18,6 +18,7 @@ import {
|
||||
} from "./common.js";
|
||||
import { ComponentBuilderDialog, getPureName, load_components, set_component_policy } from "./components-manager.js";
|
||||
import { CustomNodesManager } from "./custom-nodes-manager.js";
|
||||
import { NodeUsageAnalyzer } from "./node-usage-analyzer.js";
|
||||
import { ModelManager } from "./model-manager.js";
|
||||
import { SnapshotManager } from "./snapshot.js";
|
||||
import { buildGuiFrame, createSettingsCombo } from "./comfyui-gui-builder.js";
|
||||
@ -909,6 +910,17 @@ class ManagerMenuDialog extends ComfyDialog {
|
||||
CustomNodesManager.instance.show(CustomNodesManager.ShowMode.IN_WORKFLOW);
|
||||
}
|
||||
}),
|
||||
$el("button.cm-button", {
|
||||
type: "button",
|
||||
textContent: "Node Usage Analyzer",
|
||||
onclick:
|
||||
() => {
|
||||
if(!NodeUsageAnalyzer.instance) {
|
||||
NodeUsageAnalyzer.instance = new NodeUsageAnalyzer(app, self);
|
||||
}
|
||||
NodeUsageAnalyzer.instance.show(NodeUsageAnalyzer.SortMode.BY_PACKAGE);
|
||||
}
|
||||
}),
|
||||
|
||||
$el("div", {}, []),
|
||||
$el("button.p-button.p-component.cm-button", {
|
||||
|
||||
457
js/common.js
457
js/common.js
@ -122,9 +122,9 @@ export async function customConfirm(message) {
|
||||
let res = await
|
||||
window['app'].extensionManager.dialog
|
||||
.confirm({
|
||||
title: 'Confirm',
|
||||
message: message
|
||||
});
|
||||
title: 'Confirm',
|
||||
message: message
|
||||
});
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -164,9 +164,9 @@ export async function customPrompt(title, message) {
|
||||
let res = await
|
||||
window['app'].extensionManager.dialog
|
||||
.prompt({
|
||||
title: title,
|
||||
message: message
|
||||
});
|
||||
title: title,
|
||||
message: message
|
||||
});
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -667,4 +667,449 @@ function initTooltip () {
|
||||
document.body.addEventListener('mouseleave', mouseleaveHandler, true);
|
||||
}
|
||||
|
||||
export async function uninstallNodes(nodeList, options = {}) {
|
||||
const {
|
||||
title = `${nodeList.length} custom nodes`,
|
||||
onProgress = () => {},
|
||||
onError = () => {},
|
||||
onSuccess = () => {},
|
||||
channel = 'default',
|
||||
mode = 'default'
|
||||
} = options;
|
||||
|
||||
// Check if queue is busy
|
||||
let stats = await api.fetchApi('/manager/queue/status');
|
||||
stats = await stats.json();
|
||||
if (stats.is_processing) {
|
||||
customAlert(`[ComfyUI-Manager] There are already tasks in progress. Please try again after it is completed. (${stats.done_count}/${stats.total_count})`);
|
||||
return { success: false, error: 'Queue is busy' };
|
||||
}
|
||||
|
||||
// Confirmation dialog for uninstall
|
||||
const confirmed = await customConfirm(`Are you sure uninstall ${title}?`);
|
||||
if (!confirmed) {
|
||||
return { success: false, error: 'User cancelled' };
|
||||
}
|
||||
|
||||
let errorMsg = "";
|
||||
let target_items = [];
|
||||
|
||||
await api.fetchApi('/manager/queue/reset');
|
||||
|
||||
for (const nodeItem of nodeList) {
|
||||
target_items.push(nodeItem);
|
||||
|
||||
onProgress(`Uninstall ${nodeItem.title || nodeItem.name} ...`);
|
||||
|
||||
const data = nodeItem.originalData || nodeItem;
|
||||
data.channel = channel;
|
||||
data.mode = mode;
|
||||
data.ui_id = nodeItem.hash || md5(nodeItem.name || nodeItem.title);
|
||||
|
||||
const res = await api.fetchApi(`/manager/queue/uninstall`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (res.status != 200) {
|
||||
errorMsg = `'${nodeItem.title || nodeItem.name}': `;
|
||||
|
||||
if (res.status == 403) {
|
||||
errorMsg += `This action is not allowed with this security level configuration.\n`;
|
||||
} else if (res.status == 404) {
|
||||
errorMsg += `With the current security level configuration, only custom nodes from the <B>"default channel"</B> can be uninstalled.\n`;
|
||||
} else {
|
||||
errorMsg += await res.text() + '\n';
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (errorMsg) {
|
||||
onError(errorMsg);
|
||||
show_message("[Uninstall Errors]\n" + errorMsg);
|
||||
return { success: false, error: errorMsg, targets: target_items };
|
||||
} else {
|
||||
await api.fetchApi('/manager/queue/start');
|
||||
onSuccess(target_items);
|
||||
showTerminal();
|
||||
return { success: true, targets: target_items };
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================================================
|
||||
// Workflow Utilities Consolidation
|
||||
|
||||
export async function getWorkflowNodeTypes() {
|
||||
try {
|
||||
const res = await fetchData('/customnode/get_node_types_in_workflows');
|
||||
|
||||
if (res.status === 200) {
|
||||
return { success: true, data: res.data };
|
||||
} else if (res.status === 204) {
|
||||
// No workflows found - return empty list
|
||||
return { success: true, data: [] };
|
||||
} else {
|
||||
return { success: false, error: res.error };
|
||||
}
|
||||
} catch (error) {
|
||||
return { success: false, error: error };
|
||||
}
|
||||
}
|
||||
|
||||
export function findPackageByCnrId(cnrId, nodePackages, installedOnly = true) {
|
||||
if (!cnrId || !nodePackages) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Tier 1: Direct key match
|
||||
if (nodePackages[cnrId]) {
|
||||
const pack = nodePackages[cnrId];
|
||||
if (!installedOnly || pack.state !== "not-installed") {
|
||||
return { key: cnrId, pack: pack };
|
||||
}
|
||||
}
|
||||
|
||||
// Tier 2: Case-insensitive match
|
||||
const cnrIdLower = cnrId.toLowerCase();
|
||||
for (const packKey of Object.keys(nodePackages)) {
|
||||
if (packKey.toLowerCase() === cnrIdLower) {
|
||||
const pack = nodePackages[packKey];
|
||||
if (!installedOnly || pack.state !== "not-installed") {
|
||||
return { key: packKey, pack: pack };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tier 3: URL/reference contains match
|
||||
for (const packKey of Object.keys(nodePackages)) {
|
||||
const pack = nodePackages[packKey];
|
||||
|
||||
// Skip non-installed packages if installedOnly is true
|
||||
if (installedOnly && pack.state === "not-installed") {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if reference URL contains cnr_id
|
||||
if (pack.reference && pack.reference.includes(cnrId)) {
|
||||
return { key: packKey, pack: pack };
|
||||
}
|
||||
|
||||
// Check if any file URL contains cnr_id
|
||||
if (pack.files && Array.isArray(pack.files)) {
|
||||
for (const fileUrl of pack.files) {
|
||||
if (fileUrl.includes(cnrId)) {
|
||||
return { key: packKey, pack: pack };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function analyzeWorkflowUsage(nodePackages) {
|
||||
const result = await getWorkflowNodeTypes();
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error };
|
||||
}
|
||||
|
||||
const workflowNodeList = result.data;
|
||||
const usageMap = new Map();
|
||||
const workflowDetailsMap = new Map();
|
||||
|
||||
if (workflowNodeList && Array.isArray(workflowNodeList)) {
|
||||
const cnrIdCounts = new Map();
|
||||
const cnrIdToWorkflows = new Map();
|
||||
|
||||
// Process each workflow
|
||||
workflowNodeList.forEach((workflowObj, workflowIndex) => {
|
||||
if (workflowObj.node_types && Array.isArray(workflowObj.node_types)) {
|
||||
const workflowCnrIds = new Set();
|
||||
|
||||
// Get workflow filename
|
||||
const workflowFilename = workflowObj.workflow_file_name ||
|
||||
workflowObj.filename ||
|
||||
workflowObj.file ||
|
||||
workflowObj.name ||
|
||||
workflowObj.path ||
|
||||
`Workflow ${workflowIndex + 1}`;
|
||||
|
||||
// Count nodes per cnr_id in this workflow
|
||||
const workflowCnrIdCounts = new Map();
|
||||
workflowObj.node_types.forEach(nodeTypeObj => {
|
||||
const cnrId = nodeTypeObj.cnr_id;
|
||||
|
||||
if (cnrId && cnrId !== "comfy-core") {
|
||||
// Track unique cnr_ids per workflow
|
||||
workflowCnrIds.add(cnrId);
|
||||
|
||||
// Count nodes per cnr_id in this specific workflow
|
||||
const workflowNodeCount = workflowCnrIdCounts.get(cnrId) || 0;
|
||||
workflowCnrIdCounts.set(cnrId, workflowNodeCount + 1);
|
||||
}
|
||||
});
|
||||
|
||||
// Record workflow details for each unique cnr_id found in this workflow
|
||||
workflowCnrIds.forEach(cnrId => {
|
||||
// Count occurrences of this cnr_id across all workflows
|
||||
const currentCount = cnrIdCounts.get(cnrId) || 0;
|
||||
cnrIdCounts.set(cnrId, currentCount + 1);
|
||||
|
||||
// Track workflow details
|
||||
if (!cnrIdToWorkflows.has(cnrId)) {
|
||||
cnrIdToWorkflows.set(cnrId, []);
|
||||
}
|
||||
cnrIdToWorkflows.get(cnrId).push({
|
||||
filename: workflowFilename,
|
||||
nodeCount: workflowCnrIdCounts.get(cnrId) || 0
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Map cnr_id to installed packages with workflow details
|
||||
cnrIdCounts.forEach((count, cnrId) => {
|
||||
const workflowDetails = cnrIdToWorkflows.get(cnrId) || [];
|
||||
|
||||
const foundPackage = findPackageByCnrId(cnrId, nodePackages, true);
|
||||
if (foundPackage) {
|
||||
usageMap.set(foundPackage.key, count);
|
||||
workflowDetailsMap.set(foundPackage.key, workflowDetails);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
usageMap: usageMap,
|
||||
workflowDetailsMap: workflowDetailsMap
|
||||
};
|
||||
}
|
||||
|
||||
// Size formatting utilities - consolidated from model-manager.js and node-usage-analyzer.js
|
||||
export function formatSize(v) {
|
||||
const base = 1000;
|
||||
const units = ['', 'K', 'M', 'G', 'T', 'P'];
|
||||
const space = '';
|
||||
const postfix = 'B';
|
||||
if (v <= 0) {
|
||||
return `0${space}${postfix}`;
|
||||
}
|
||||
for (let i = 0, l = units.length; i < l; i++) {
|
||||
const min = Math.pow(base, i);
|
||||
const max = Math.pow(base, i + 1);
|
||||
if (v > min && v <= max) {
|
||||
const unit = units[i];
|
||||
if (unit) {
|
||||
const n = v / min;
|
||||
const nl = n.toString().split('.')[0].length;
|
||||
const fl = Math.max(3 - nl, 1);
|
||||
v = n.toFixed(fl);
|
||||
}
|
||||
v = v + space + unit + postfix;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// for size sort
|
||||
export function sizeToBytes(v) {
|
||||
if (typeof v === "number") {
|
||||
return v;
|
||||
}
|
||||
if (typeof v === "string") {
|
||||
const n = parseFloat(v);
|
||||
const unit = v.replace(/[0-9.B]+/g, "").trim().toUpperCase();
|
||||
if (unit === "K") {
|
||||
return n * 1000;
|
||||
}
|
||||
if (unit === "M") {
|
||||
return n * 1000 * 1000;
|
||||
}
|
||||
if (unit === "G") {
|
||||
return n * 1000 * 1000 * 1000;
|
||||
}
|
||||
if (unit === "T") {
|
||||
return n * 1000 * 1000 * 1000 * 1000;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// Flyover component - consolidated from custom-nodes-manager.js and node-usage-analyzer.js
|
||||
export function createFlyover(container, options = {}) {
|
||||
const {
|
||||
enableHover = false,
|
||||
hoverHandler = null,
|
||||
context = null
|
||||
} = options;
|
||||
|
||||
const $flyover = document.createElement("div");
|
||||
$flyover.className = "cn-flyover";
|
||||
$flyover.innerHTML = `<div class="cn-flyover-header">
|
||||
<div class="cn-flyover-close">${icons.arrowRight}</div>
|
||||
<div class="cn-flyover-title"></div>
|
||||
<div class="cn-flyover-close">${icons.close}</div>
|
||||
</div>
|
||||
<div class="cn-flyover-body"></div>`
|
||||
container.appendChild($flyover);
|
||||
|
||||
const $flyoverTitle = $flyover.querySelector(".cn-flyover-title");
|
||||
const $flyoverBody = $flyover.querySelector(".cn-flyover-body");
|
||||
|
||||
let width = '50%';
|
||||
let visible = false;
|
||||
|
||||
let timeHide;
|
||||
const closeHandler = (e) => {
|
||||
if ($flyover === e.target || $flyover.contains(e.target)) {
|
||||
return;
|
||||
}
|
||||
clearTimeout(timeHide);
|
||||
timeHide = setTimeout(() => {
|
||||
flyover.hide();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
const displayHandler = () => {
|
||||
if (visible) {
|
||||
$flyover.classList.remove("cn-slide-in-right");
|
||||
} else {
|
||||
$flyover.classList.remove("cn-slide-out-right");
|
||||
$flyover.style.width = '0px';
|
||||
$flyover.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
const flyover = {
|
||||
show: (titleHtml, bodyHtml) => {
|
||||
clearTimeout(timeHide);
|
||||
if (context && context.element) {
|
||||
context.element.removeEventListener("click", closeHandler);
|
||||
}
|
||||
$flyoverTitle.innerHTML = titleHtml;
|
||||
$flyoverBody.innerHTML = bodyHtml;
|
||||
$flyover.style.display = "block";
|
||||
$flyover.style.width = width;
|
||||
if(!visible) {
|
||||
$flyover.classList.add("cn-slide-in-right");
|
||||
}
|
||||
visible = true;
|
||||
setTimeout(() => {
|
||||
if (context && context.element) {
|
||||
context.element.addEventListener("click", closeHandler);
|
||||
}
|
||||
}, 100);
|
||||
},
|
||||
hide: (now) => {
|
||||
visible = false;
|
||||
if (context && context.element) {
|
||||
context.element.removeEventListener("click", closeHandler);
|
||||
}
|
||||
if(now) {
|
||||
displayHandler();
|
||||
return;
|
||||
}
|
||||
$flyover.classList.add("cn-slide-out-right");
|
||||
}
|
||||
}
|
||||
|
||||
$flyover.addEventListener("animationend", (e) => {
|
||||
displayHandler();
|
||||
});
|
||||
|
||||
// Add hover handlers if enabled
|
||||
if (enableHover && hoverHandler) {
|
||||
$flyover.addEventListener("mouseenter", hoverHandler, true);
|
||||
$flyover.addEventListener("mouseleave", hoverHandler, true);
|
||||
}
|
||||
|
||||
$flyover.addEventListener("click", (e) => {
|
||||
if(e.target.classList.contains("cn-flyover-close")) {
|
||||
flyover.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
// Forward other click events to the provided handler or context
|
||||
if (context && context.handleFlyoverClick) {
|
||||
context.handleFlyoverClick(e);
|
||||
}
|
||||
});
|
||||
|
||||
return flyover;
|
||||
}
|
||||
|
||||
// Shared UI State Methods - consolidated from multiple managers
|
||||
export function createUIStateManager(element, selectors) {
|
||||
return {
|
||||
showSelection: (msg) => {
|
||||
const el = element.querySelector(selectors.selection);
|
||||
if (el) el.innerHTML = msg;
|
||||
},
|
||||
|
||||
showError: (err) => {
|
||||
const el = element.querySelector(selectors.message);
|
||||
if (el) {
|
||||
const msg = err ? `<font color="red">${err}</font>` : "";
|
||||
el.innerHTML = msg;
|
||||
}
|
||||
},
|
||||
|
||||
showMessage: (msg, color) => {
|
||||
const el = element.querySelector(selectors.message);
|
||||
if (el) {
|
||||
if (color) {
|
||||
msg = `<font color="${color}">${msg}</font>`;
|
||||
}
|
||||
el.innerHTML = msg;
|
||||
}
|
||||
},
|
||||
|
||||
showStatus: (msg, color) => {
|
||||
const el = element.querySelector(selectors.status);
|
||||
if (el) {
|
||||
if (color) {
|
||||
msg = `<font color="${color}">${msg}</font>`;
|
||||
}
|
||||
el.innerHTML = msg;
|
||||
}
|
||||
},
|
||||
|
||||
showLoading: (grid) => {
|
||||
if (grid) {
|
||||
grid.showLoading();
|
||||
grid.showMask({
|
||||
opacity: 0.05
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
hideLoading: (grid) => {
|
||||
if (grid) {
|
||||
grid.hideLoading();
|
||||
grid.hideMask();
|
||||
}
|
||||
},
|
||||
|
||||
showRefresh: () => {
|
||||
const el = element.querySelector(selectors.refresh);
|
||||
if (el) el.style.display = "block";
|
||||
},
|
||||
|
||||
showStop: () => {
|
||||
const el = element.querySelector(selectors.stop);
|
||||
if (el) el.style.display = "block";
|
||||
},
|
||||
|
||||
hideStop: () => {
|
||||
const el = element.querySelector(selectors.stop);
|
||||
if (el) el.style.display = "none";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
initTooltip();
|
||||
@ -8,7 +8,7 @@ import {
|
||||
fetchData, md5, icons, show_message, customConfirm, customAlert, customPrompt,
|
||||
sanitizeHTML, infoToast, showTerminal, setNeedRestart,
|
||||
storeColumnWidth, restoreColumnWidth, getTimeAgo, copyText, loadCss,
|
||||
showPopover, hidePopover, handle403Response
|
||||
showPopover, hidePopover, getWorkflowNodeTypes, findPackageByCnrId, analyzeWorkflowUsage, createFlyover
|
||||
} from "./common.js";
|
||||
|
||||
// https://cenfun.github.io/turbogrid/api.html
|
||||
@ -42,6 +42,8 @@ const ShowMode = {
|
||||
FAVORITES: "Favorites",
|
||||
ALTERNATIVES: "Alternatives",
|
||||
IN_WORKFLOW: "In Workflow",
|
||||
USED_IN_ANY_WORKFLOW: "Used In Any Workflow",
|
||||
NOT_USED_IN_ANY_WORKFLOW: "Installed and Unused",
|
||||
};
|
||||
|
||||
export class CustomNodesManager {
|
||||
@ -271,6 +273,14 @@ export class CustomNodesManager {
|
||||
label: "In Workflow",
|
||||
value: ShowMode.IN_WORKFLOW,
|
||||
hasData: false
|
||||
}, {
|
||||
label: "Used In Any Workflow",
|
||||
value: ShowMode.USED_IN_ANY_WORKFLOW,
|
||||
hasData: false
|
||||
}, {
|
||||
label: "Installed and Unused",
|
||||
value: ShowMode.NOT_USED_IN_ANY_WORKFLOW,
|
||||
hasData: false
|
||||
}, {
|
||||
label: "Missing",
|
||||
value: ShowMode.MISSING,
|
||||
@ -521,7 +531,11 @@ export class CustomNodesManager {
|
||||
const grid = new TG.Grid(container);
|
||||
this.grid = grid;
|
||||
|
||||
this.flyover = this.createFlyover(container);
|
||||
this.flyover = createFlyover(container, {
|
||||
enableHover: true,
|
||||
hoverHandler: this.handleFlyoverHover.bind(this),
|
||||
context: this
|
||||
});
|
||||
|
||||
let prevViewRowsLength = -1;
|
||||
grid.bind('onUpdated', (e, d) => {
|
||||
@ -1063,143 +1077,63 @@ export class CustomNodesManager {
|
||||
hidePopover();
|
||||
}
|
||||
|
||||
createFlyover(container) {
|
||||
const $flyover = document.createElement("div");
|
||||
$flyover.className = "cn-flyover";
|
||||
$flyover.innerHTML = `<div class="cn-flyover-header">
|
||||
<div class="cn-flyover-close">${icons.arrowRight}</div>
|
||||
<div class="cn-flyover-title"></div>
|
||||
<div class="cn-flyover-close">${icons.close}</div>
|
||||
</div>
|
||||
<div class="cn-flyover-body"></div>`
|
||||
container.appendChild($flyover);
|
||||
|
||||
const $flyoverTitle = $flyover.querySelector(".cn-flyover-title");
|
||||
const $flyoverBody = $flyover.querySelector(".cn-flyover-body");
|
||||
|
||||
let width = '50%';
|
||||
let visible = false;
|
||||
|
||||
let timeHide;
|
||||
const closeHandler = (e) => {
|
||||
if ($flyover === e.target || $flyover.contains(e.target)) {
|
||||
return;
|
||||
}
|
||||
clearTimeout(timeHide);
|
||||
timeHide = setTimeout(() => {
|
||||
flyover.hide();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
const hoverHandler = (e) => {
|
||||
if(e.type === "mouseenter") {
|
||||
if(e.target.classList.contains("cn-nodes-name")) {
|
||||
this.showNodePreview(e.target);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.hideNodePreview();
|
||||
}
|
||||
|
||||
const displayHandler = () => {
|
||||
if (visible) {
|
||||
$flyover.classList.remove("cn-slide-in-right");
|
||||
} else {
|
||||
$flyover.classList.remove("cn-slide-out-right");
|
||||
$flyover.style.width = '0px';
|
||||
$flyover.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
const flyover = {
|
||||
show: (titleHtml, bodyHtml) => {
|
||||
clearTimeout(timeHide);
|
||||
this.element.removeEventListener("click", closeHandler);
|
||||
$flyoverTitle.innerHTML = titleHtml;
|
||||
$flyoverBody.innerHTML = bodyHtml;
|
||||
$flyover.style.display = "block";
|
||||
$flyover.style.width = width;
|
||||
if(!visible) {
|
||||
$flyover.classList.add("cn-slide-in-right");
|
||||
}
|
||||
visible = true;
|
||||
setTimeout(() => {
|
||||
this.element.addEventListener("click", closeHandler);
|
||||
}, 100);
|
||||
},
|
||||
hide: (now) => {
|
||||
visible = false;
|
||||
this.element.removeEventListener("click", closeHandler);
|
||||
if(now) {
|
||||
displayHandler();
|
||||
return;
|
||||
}
|
||||
$flyover.classList.add("cn-slide-out-right");
|
||||
}
|
||||
}
|
||||
|
||||
$flyover.addEventListener("animationend", (e) => {
|
||||
displayHandler();
|
||||
});
|
||||
|
||||
$flyover.addEventListener("mouseenter", hoverHandler, true);
|
||||
$flyover.addEventListener("mouseleave", hoverHandler, true);
|
||||
|
||||
$flyover.addEventListener("click", (e) => {
|
||||
|
||||
handleFlyoverHover(e) {
|
||||
if(e.type === "mouseenter") {
|
||||
if(e.target.classList.contains("cn-nodes-name")) {
|
||||
const nodeName = e.target.innerText;
|
||||
const nodeItem = this.nodeMap[nodeName];
|
||||
if (!nodeItem) {
|
||||
copyText(nodeName).then((res) => {
|
||||
if (res) {
|
||||
e.target.setAttribute("action", "Copied");
|
||||
e.target.classList.add("action");
|
||||
setTimeout(() => {
|
||||
e.target.classList.remove("action");
|
||||
e.target.removeAttribute("action");
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.showNodePreview(e.target);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.hideNodePreview();
|
||||
}
|
||||
|
||||
const [x, y, w, h] = app.canvas.ds.visible_area;
|
||||
const dpi = Math.max(window.devicePixelRatio ?? 1, 1);
|
||||
const node = window.LiteGraph?.createNode(
|
||||
nodeItem.name,
|
||||
nodeItem.display_name,
|
||||
{
|
||||
pos: [x + (w-300) / dpi / 2, y]
|
||||
handleFlyoverClick(e) {
|
||||
if(e.target.classList.contains("cn-nodes-name")) {
|
||||
const nodeName = e.target.innerText;
|
||||
const nodeItem = this.nodeMap[nodeName];
|
||||
if (!nodeItem) {
|
||||
copyText(nodeName).then((res) => {
|
||||
if (res) {
|
||||
e.target.setAttribute("action", "Copied");
|
||||
e.target.classList.add("action");
|
||||
setTimeout(() => {
|
||||
e.target.classList.remove("action");
|
||||
e.target.removeAttribute("action");
|
||||
}, 1000);
|
||||
}
|
||||
);
|
||||
if (node) {
|
||||
app.graph.add(node);
|
||||
e.target.setAttribute("action", "Added to Workflow");
|
||||
e.target.classList.add("action");
|
||||
setTimeout(() => {
|
||||
e.target.classList.remove("action");
|
||||
e.target.removeAttribute("action");
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
});
|
||||
return;
|
||||
}
|
||||
if(e.target.classList.contains("cn-nodes-pack")) {
|
||||
const hash = e.target.getAttribute("hash");
|
||||
const rowItem = this.grid.getRowItemBy("hash", hash);
|
||||
//console.log(rowItem);
|
||||
this.grid.scrollToRow(rowItem);
|
||||
this.addHighlight(rowItem);
|
||||
return;
|
||||
}
|
||||
if(e.target.classList.contains("cn-flyover-close")) {
|
||||
flyover.hide();
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
return flyover;
|
||||
const [x, y, w, h] = app.canvas.ds.visible_area;
|
||||
const dpi = Math.max(window.devicePixelRatio ?? 1, 1);
|
||||
const node = window.LiteGraph?.createNode(
|
||||
nodeItem.name,
|
||||
nodeItem.display_name,
|
||||
{
|
||||
pos: [x + (w-300) / dpi / 2, y]
|
||||
}
|
||||
);
|
||||
if (node) {
|
||||
app.graph.add(node);
|
||||
e.target.setAttribute("action", "Added to Workflow");
|
||||
e.target.classList.add("action");
|
||||
setTimeout(() => {
|
||||
e.target.classList.remove("action");
|
||||
e.target.removeAttribute("action");
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if(e.target.classList.contains("cn-nodes-pack")) {
|
||||
const hash = e.target.getAttribute("hash");
|
||||
const rowItem = this.grid.getRowItemBy("hash", hash);
|
||||
//console.log(rowItem);
|
||||
this.grid.scrollToRow(rowItem);
|
||||
this.addHighlight(rowItem);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
showNodes(d) {
|
||||
@ -1874,7 +1808,10 @@ export class CustomNodesManager {
|
||||
for(let k in allUsedNodes) {
|
||||
var item;
|
||||
if(allUsedNodes[k].properties.cnr_id) {
|
||||
item = this.custom_nodes[allUsedNodes[k].properties.cnr_id];
|
||||
const foundPackage = findPackageByCnrId(allUsedNodes[k].properties.cnr_id, this.custom_nodes, false);
|
||||
if (foundPackage) {
|
||||
item = foundPackage.pack;
|
||||
}
|
||||
}
|
||||
else if(allUsedNodes[k].properties.aux_id) {
|
||||
item = aux_id_to_pack[allUsedNodes[k].properties.aux_id];
|
||||
@ -1921,6 +1858,48 @@ export class CustomNodesManager {
|
||||
return hashMap;
|
||||
}
|
||||
|
||||
async getUsedInAnyWorkflow() {
|
||||
this.showStatus(`Loading workflow usage analysis ...`);
|
||||
|
||||
const result = await analyzeWorkflowUsage(this.custom_nodes);
|
||||
|
||||
if (!result.success) {
|
||||
this.showError(`Failed to get workflow data: ${result.error}`);
|
||||
return {};
|
||||
}
|
||||
|
||||
const hashMap = {};
|
||||
|
||||
// Convert usage map keys to hash map
|
||||
result.usageMap.forEach((count, packageKey) => {
|
||||
const pack = this.custom_nodes[packageKey];
|
||||
if (pack && pack.hash) {
|
||||
hashMap[pack.hash] = true;
|
||||
}
|
||||
});
|
||||
|
||||
return hashMap;
|
||||
}
|
||||
|
||||
async getNotUsedInAnyWorkflow() {
|
||||
this.showStatus(`Loading workflow usage analysis ...`);
|
||||
|
||||
// Get the used packages first using common utility
|
||||
const usedHashMap = await this.getUsedInAnyWorkflow();
|
||||
const notUsedHashMap = {};
|
||||
|
||||
// Find all installed packages that are NOT in the used list
|
||||
for(let k in this.custom_nodes) {
|
||||
let nodepack = this.custom_nodes[k];
|
||||
// Only consider installed packages
|
||||
if (nodepack.state !== "not-installed" && !usedHashMap[nodepack.hash]) {
|
||||
notUsedHashMap[nodepack.hash] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return notUsedHashMap;
|
||||
}
|
||||
|
||||
async loadData(show_mode = ShowMode.NORMAL) {
|
||||
const isElectron = 'electronAPI' in window;
|
||||
|
||||
@ -1990,6 +1969,10 @@ export class CustomNodesManager {
|
||||
hashMap = await this.getFavorites();
|
||||
} else if(this.show_mode == ShowMode.IN_WORKFLOW) {
|
||||
hashMap = await this.getNodepackInWorkflow();
|
||||
} else if(this.show_mode == ShowMode.USED_IN_ANY_WORKFLOW) {
|
||||
hashMap = await this.getUsedInAnyWorkflow();
|
||||
} else if(this.show_mode == ShowMode.NOT_USED_IN_ANY_WORKFLOW) {
|
||||
hashMap = await this.getNotUsedInAnyWorkflow();
|
||||
}
|
||||
filterItem.hashMap = hashMap;
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ import { $el } from "../../scripts/ui.js";
|
||||
import {
|
||||
manager_instance, rebootAPI,
|
||||
fetchData, md5, icons, show_message, customAlert, infoToast, showTerminal,
|
||||
storeColumnWidth, restoreColumnWidth, loadCss, handle403Response
|
||||
storeColumnWidth, restoreColumnWidth, loadCss, formatSize, sizeToBytes
|
||||
} from "./common.js";
|
||||
import { api } from "../../scripts/api.js";
|
||||
|
||||
@ -359,7 +359,7 @@ export class ModelManager {
|
||||
width: 100,
|
||||
formatter: (size) => {
|
||||
if (typeof size === "number") {
|
||||
return this.formatSize(size);
|
||||
return formatSize(size);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
@ -582,7 +582,7 @@ export class ModelManager {
|
||||
models.forEach((item, i) => {
|
||||
const { type, base, name, reference, installed } = item;
|
||||
item.originalData = JSON.parse(JSON.stringify(item));
|
||||
item.size = this.sizeToBytes(item.size);
|
||||
item.size = sizeToBytes(item.size);
|
||||
item.hash = md5(name + reference);
|
||||
item.id = i + 1;
|
||||
|
||||
@ -659,7 +659,6 @@ export class ModelManager {
|
||||
const { models } = res.data;
|
||||
|
||||
this.modelList = this.getModelList(models);
|
||||
// console.log("models", this.modelList);
|
||||
|
||||
this.updateFilter();
|
||||
|
||||
@ -671,56 +670,6 @@ export class ModelManager {
|
||||
|
||||
// ===========================================================================================
|
||||
|
||||
formatSize(v) {
|
||||
const base = 1000;
|
||||
const units = ['', 'K', 'M', 'G', 'T', 'P'];
|
||||
const space = '';
|
||||
const postfix = 'B';
|
||||
if (v <= 0) {
|
||||
return `0${space}${postfix}`;
|
||||
}
|
||||
for (let i = 0, l = units.length; i < l; i++) {
|
||||
const min = Math.pow(base, i);
|
||||
const max = Math.pow(base, i + 1);
|
||||
if (v > min && v <= max) {
|
||||
const unit = units[i];
|
||||
if (unit) {
|
||||
const n = v / min;
|
||||
const nl = n.toString().split('.')[0].length;
|
||||
const fl = Math.max(3 - nl, 1);
|
||||
v = n.toFixed(fl);
|
||||
}
|
||||
v = v + space + unit + postfix;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// for size sort
|
||||
sizeToBytes(v) {
|
||||
if (typeof v === "number") {
|
||||
return v;
|
||||
}
|
||||
if (typeof v === "string") {
|
||||
const n = parseFloat(v);
|
||||
const unit = v.replace(/[0-9.B]+/g, "").trim().toUpperCase();
|
||||
if (unit === "K") {
|
||||
return n * 1000;
|
||||
}
|
||||
if (unit === "M") {
|
||||
return n * 1000 * 1000;
|
||||
}
|
||||
if (unit === "G") {
|
||||
return n * 1000 * 1000 * 1000;
|
||||
}
|
||||
if (unit === "T") {
|
||||
return n * 1000 * 1000 * 1000 * 1000;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
showSelection(msg) {
|
||||
this.element.querySelector(".cmm-manager-selection").innerHTML = msg;
|
||||
}
|
||||
|
||||
699
js/node-usage-analyzer.css
Normal file
699
js/node-usage-analyzer.css
Normal file
@ -0,0 +1,699 @@
|
||||
.nu-manager {
|
||||
--grid-font: -apple-system, BlinkMacSystemFont, "Segue UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
|
||||
z-index: 1099;
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
color: var(--fg-color);
|
||||
font-family: arial, sans-serif;
|
||||
text-underline-offset: 3px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.nu-manager .nu-flex-auto {
|
||||
flex: auto;
|
||||
}
|
||||
|
||||
.nu-manager button {
|
||||
font-size: 16px;
|
||||
color: var(--input-text);
|
||||
background-color: var(--comfy-input-bg);
|
||||
border-radius: 8px;
|
||||
border-color: var(--border-color);
|
||||
border-style: solid;
|
||||
margin: 0;
|
||||
padding: 4px 8px;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.nu-manager button:disabled,
|
||||
.nu-manager input:disabled,
|
||||
.nu-manager select:disabled {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.nu-manager button:disabled {
|
||||
background-color: var(--comfy-input-bg);
|
||||
}
|
||||
|
||||
.nu-manager .nu-manager-restart {
|
||||
display: none;
|
||||
background-color: #500000;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nu-manager .nu-manager-stop {
|
||||
display: none;
|
||||
background-color: #500000;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nu-manager .nu-manager-back {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.arrow-icon {
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
margin-right: 5px;
|
||||
transform: translateY(2px);
|
||||
}
|
||||
|
||||
.cn-icon {
|
||||
display: block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.cn-icon svg {
|
||||
display: block;
|
||||
margin: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.nu-manager-header {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 5px;
|
||||
align-items: center;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.nu-manager-header label {
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nu-manager-filter {
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
.nu-manager-keywords {
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
padding: 0 5px 0 26px;
|
||||
background-size: 16px;
|
||||
background-position: 5px center;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20viewBox%3D%220%200%2024%2024%22%20width%3D%22100%25%22%20height%3D%22100%25%22%20pointer-events%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22none%22%20stroke%3D%22%23888%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20stroke-width%3D%222%22%20d%3D%22m21%2021-4.486-4.494M19%2010.5a8.5%208.5%200%201%201-17%200%208.5%208.5%200%200%201%2017%200%22%2F%3E%3C%2Fsvg%3E");
|
||||
}
|
||||
|
||||
.nu-manager-status {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.nu-manager-grid {
|
||||
flex: auto;
|
||||
border: 1px solid var(--border-color);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nu-manager-selection {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nu-manager-message {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nu-manager-footer {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nu-manager-grid .tg-turbogrid {
|
||||
font-family: var(--grid-font);
|
||||
font-size: 15px;
|
||||
background: var(--bg-color);
|
||||
}
|
||||
|
||||
.nu-manager-grid .tg-turbogrid .tg-highlight::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
content: "";
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
background-color: #80bdff11;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.nu-manager-grid .nu-pack-name a {
|
||||
color: skyblue;
|
||||
text-decoration: none;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.nu-manager-grid .cn-pack-desc a {
|
||||
color: #5555FF;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.nu-manager-grid .tg-cell a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.nu-manager-grid .cn-pack-version {
|
||||
line-height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.nu-manager-grid .cn-pack-nodes {
|
||||
line-height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: 5px;
|
||||
cursor: pointer;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.nu-manager-grid .cn-pack-nodes:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.nu-manager-grid .cn-pack-conflicts {
|
||||
color: orange;
|
||||
}
|
||||
|
||||
.cn-popover {
|
||||
position: fixed;
|
||||
z-index: 10000;
|
||||
padding: 20px;
|
||||
color: #1e1e1e;
|
||||
filter: drop-shadow(1px 5px 5px rgb(0 0 0 / 30%));
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.cn-flyover {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
display: none;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
background-color: var(--comfy-menu-bg);
|
||||
animation-duration: 0.2s;
|
||||
animation-fill-mode: both;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.cn-flyover::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
content: "";
|
||||
z-index: 10;
|
||||
display: block;
|
||||
width: 10px;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
left: -10px;
|
||||
background-image: linear-gradient(to left, rgb(0 0 0 / 20%), rgb(0 0 0 / 0%));
|
||||
}
|
||||
|
||||
.cn-flyover-header {
|
||||
height: 45px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.cn-flyover-close {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 10px;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
opacity: 0.8;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.cn-flyover-close:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.cn-flyover-close svg {
|
||||
display: block;
|
||||
margin: 0;
|
||||
pointer-events: none;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.cn-flyover-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: bold;
|
||||
gap: 10px;
|
||||
flex: auto;
|
||||
}
|
||||
|
||||
.cn-flyover-body {
|
||||
height: calc(100% - 45px);
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
background-color: var(--comfy-menu-secondary-bg);
|
||||
}
|
||||
|
||||
@keyframes cn-slide-in-right {
|
||||
from {
|
||||
visibility: visible;
|
||||
transform: translate3d(100%, 0, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.cn-slide-in-right {
|
||||
animation-name: cn-slide-in-right;
|
||||
}
|
||||
|
||||
@keyframes cn-slide-out-right {
|
||||
from {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
visibility: hidden;
|
||||
transform: translate3d(100%, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.cn-slide-out-right {
|
||||
animation-name: cn-slide-out-right;
|
||||
}
|
||||
|
||||
.cn-nodes-list {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.cn-nodes-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.cn-nodes-row:nth-child(odd) {
|
||||
background-color: rgb(0 0 0 / 5%);
|
||||
}
|
||||
|
||||
.cn-nodes-row:hover {
|
||||
background-color: rgb(0 0 0 / 10%);
|
||||
}
|
||||
|
||||
.cn-nodes-sn {
|
||||
text-align: right;
|
||||
min-width: 35px;
|
||||
color: var(--drag-text);
|
||||
flex-shrink: 0;
|
||||
font-size: 12px;
|
||||
padding: 8px 5px;
|
||||
}
|
||||
|
||||
.cn-nodes-name {
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
padding: 8px 5px;
|
||||
}
|
||||
|
||||
.cn-nodes-name::after {
|
||||
content: attr(action);
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
top: 50%;
|
||||
left: 100%;
|
||||
transform: translate(5px, -50%);
|
||||
font-size: 12px;
|
||||
color: var(--drag-text);
|
||||
background-color: var(--comfy-input-bg);
|
||||
border-radius: 10px;
|
||||
border: 1px solid var(--border-color);
|
||||
padding: 3px 8px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.cn-nodes-name.action::after {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.cn-nodes-name:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.cn-nodes-conflict .cn-nodes-name,
|
||||
.cn-nodes-conflict .cn-icon {
|
||||
color: orange;
|
||||
}
|
||||
|
||||
.cn-conflicts-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 5px;
|
||||
align-items: center;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.cn-conflicts-list b {
|
||||
font-weight: normal;
|
||||
color: var(--descrip-text);
|
||||
}
|
||||
|
||||
.cn-nodes-pack {
|
||||
cursor: pointer;
|
||||
color: skyblue;
|
||||
}
|
||||
|
||||
.cn-nodes-pack:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.cn-pack-badge {
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
background-color: var(--comfy-input-bg);
|
||||
border-radius: 10px;
|
||||
border: 1px solid var(--border-color);
|
||||
padding: 3px 8px;
|
||||
color: var(--error-text);
|
||||
}
|
||||
|
||||
.cn-preview {
|
||||
min-width: 300px;
|
||||
max-width: 500px;
|
||||
min-height: 120px;
|
||||
overflow: hidden;
|
||||
font-size: 12px;
|
||||
pointer-events: none;
|
||||
padding: 12px;
|
||||
color: var(--fg-color);
|
||||
}
|
||||
|
||||
.cn-preview-header {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid var(--comfy-input-bg);
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.cn-preview-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background-color: grey;
|
||||
position: relative;
|
||||
filter: drop-shadow(1px 2px 3px rgb(0 0 0 / 30%));
|
||||
}
|
||||
|
||||
.cn-preview-dot.cn-preview-optional::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background-color: var(--comfy-input-bg);
|
||||
border-radius: 50%;
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
}
|
||||
|
||||
.cn-preview-dot.cn-preview-grid {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.cn-preview-dot.cn-preview-grid::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
border-left: 1px solid var(--comfy-input-bg);
|
||||
border-right: 1px solid var(--comfy-input-bg);
|
||||
width: 4px;
|
||||
height: 100%;
|
||||
left: 2px;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.cn-preview-dot.cn-preview-grid::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
border-top: 1px solid var(--comfy-input-bg);
|
||||
border-bottom: 1px solid var(--comfy-input-bg);
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
left: 0;
|
||||
top: 2px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.cn-preview-name {
|
||||
flex: auto;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.cn-preview-io {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 10px 10px;
|
||||
}
|
||||
|
||||
.cn-preview-column > div {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
height: 18px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.cn-preview-input {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.cn-preview-output {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.cn-preview-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
padding: 0 10px 10px 10px;
|
||||
}
|
||||
|
||||
.cn-preview-switch {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: var(--bg-color);
|
||||
border: 2px solid var(--border-color);
|
||||
border-radius: 10px;
|
||||
text-wrap: nowrap;
|
||||
padding: 2px 20px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.cn-preview-switch::before,
|
||||
.cn-preview-switch::after {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
top: 50%;
|
||||
transform: translate(0, -50%);
|
||||
color: var(--fg-color);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.cn-preview-switch::before {
|
||||
content: "◀";
|
||||
left: 5px;
|
||||
}
|
||||
|
||||
.cn-preview-switch::after {
|
||||
content: "▶";
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
.cn-preview-value {
|
||||
color: var(--descrip-text);
|
||||
}
|
||||
|
||||
.cn-preview-string {
|
||||
min-height: 30px;
|
||||
max-height: 300px;
|
||||
background: var(--bg-color);
|
||||
color: var(--descrip-text);
|
||||
border-radius: 3px;
|
||||
padding: 3px 5px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.cn-preview-description {
|
||||
margin: 0px 10px 10px 10px;
|
||||
padding: 6px;
|
||||
background: var(--border-color);
|
||||
color: var(--descrip-text);
|
||||
border-radius: 5px;
|
||||
font-style: italic;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.cn-tag-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 5px;
|
||||
align-items: center;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.cn-tag-list > div {
|
||||
background-color: var(--border-color);
|
||||
border-radius: 5px;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.cn-install-buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
padding: 3px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.cn-selected-buttons {
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
align-items: center;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.nu-manager .cn-btn-enable {
|
||||
background-color: #333399;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nu-manager .cn-btn-disable {
|
||||
background-color: #442277;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nu-manager .cn-btn-update {
|
||||
background-color: #1155AA;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nu-manager .cn-btn-try-update {
|
||||
background-color: Gray;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nu-manager .cn-btn-try-fix {
|
||||
background-color: #6495ED;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nu-manager .cn-btn-import-failed {
|
||||
background-color: #AA1111;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nu-manager .cn-btn-install {
|
||||
background-color: black;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nu-manager .cn-btn-try-install {
|
||||
background-color: Gray;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nu-manager .cn-btn-uninstall {
|
||||
background-color: #993333;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nu-manager .cn-btn-reinstall {
|
||||
background-color: #993333;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nu-manager .cn-btn-switch {
|
||||
background-color: #448833;
|
||||
color: white;
|
||||
|
||||
}
|
||||
|
||||
@keyframes nu-btn-loading-bg {
|
||||
0% {
|
||||
left: 0;
|
||||
}
|
||||
100% {
|
||||
left: -105px;
|
||||
}
|
||||
}
|
||||
|
||||
.nu-manager button.nu-btn-loading {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-color: rgb(0 119 207 / 80%);
|
||||
background-color: var(--comfy-input-bg);
|
||||
}
|
||||
|
||||
.nu-manager button.nu-btn-loading::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
content: "";
|
||||
width: 500px;
|
||||
height: 100%;
|
||||
background-image: repeating-linear-gradient(
|
||||
-45deg,
|
||||
rgb(0 119 207 / 30%),
|
||||
rgb(0 119 207 / 30%) 10px,
|
||||
transparent 10px,
|
||||
transparent 15px
|
||||
);
|
||||
animation: nu-btn-loading-bg 2s linear infinite;
|
||||
}
|
||||
|
||||
.nu-manager-light .nu-pack-name a {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.nu-manager-light .cm-warn-note {
|
||||
background-color: #ccc !important;
|
||||
}
|
||||
|
||||
.nu-manager-light .cn-btn-install {
|
||||
background-color: #333;
|
||||
}
|
||||
742
js/node-usage-analyzer.js
Normal file
742
js/node-usage-analyzer.js
Normal file
@ -0,0 +1,742 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { $el } from "../../scripts/ui.js";
|
||||
import {
|
||||
manager_instance,
|
||||
fetchData, md5, show_message, customAlert, infoToast, showTerminal,
|
||||
storeColumnWidth, restoreColumnWidth, loadCss, uninstallNodes,
|
||||
analyzeWorkflowUsage, sizeToBytes, createFlyover, createUIStateManager
|
||||
} from "./common.js";
|
||||
import { api } from "../../scripts/api.js";
|
||||
|
||||
// https://cenfun.github.io/turbogrid/api.html
|
||||
import TG from "./turbogrid.esm.js";
|
||||
|
||||
loadCss("./node-usage-analyzer.css");
|
||||
|
||||
const gridId = "model";
|
||||
|
||||
const pageHtml = `
|
||||
<div class="nu-manager-header">
|
||||
<div class="nu-manager-status"></div>
|
||||
<input type="text" class="nu-manager-keywords" placeholder="Filter keywords..." />
|
||||
<div class="nu-flex-auto"></div>
|
||||
</div>
|
||||
<div class="nu-manager-grid"></div>
|
||||
<div class="nu-manager-selection"></div>
|
||||
<div class="nu-manager-message"></div>
|
||||
<div class="nu-manager-footer">
|
||||
<button class="nu-manager-back">
|
||||
<svg class="arrow-icon" width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2 8H18M2 8L8 2M2 8L8 14" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
Back
|
||||
</button>
|
||||
<button class="nu-manager-refresh">Refresh</button>
|
||||
<button class="nu-manager-stop">Stop</button>
|
||||
<div class="nu-flex-auto"></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
export class NodeUsageAnalyzer {
|
||||
static instance = null;
|
||||
|
||||
static SortMode = {
|
||||
BY_PACKAGE: 'by_package'
|
||||
};
|
||||
|
||||
constructor(app, manager_dialog) {
|
||||
this.app = app;
|
||||
this.manager_dialog = manager_dialog;
|
||||
this.id = "nu-manager";
|
||||
|
||||
this.filter = '';
|
||||
this.type = '';
|
||||
this.base = '';
|
||||
this.keywords = '';
|
||||
|
||||
this.init();
|
||||
|
||||
// Initialize shared UI state manager
|
||||
this.ui = createUIStateManager(this.element, {
|
||||
selection: ".nu-manager-selection",
|
||||
message: ".nu-manager-message",
|
||||
status: ".nu-manager-status",
|
||||
refresh: ".nu-manager-refresh",
|
||||
stop: ".nu-manager-stop"
|
||||
});
|
||||
|
||||
api.addEventListener("cm-queue-status", this.onQueueStatus);
|
||||
}
|
||||
|
||||
init() {
|
||||
this.element = $el("div", {
|
||||
parent: document.body,
|
||||
className: "comfy-modal nu-manager"
|
||||
});
|
||||
this.element.innerHTML = pageHtml;
|
||||
this.bindEvents();
|
||||
this.initGrid();
|
||||
}
|
||||
|
||||
bindEvents() {
|
||||
const eventsMap = {
|
||||
".nu-manager-selection": {
|
||||
click: (e) => {
|
||||
const target = e.target;
|
||||
const mode = target.getAttribute("mode");
|
||||
if (mode === "install") {
|
||||
this.installModels(this.selectedModels, target);
|
||||
} else if (mode === "uninstall") {
|
||||
this.uninstallModels(this.selectedModels, target);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
".nu-manager-refresh": {
|
||||
click: () => {
|
||||
app.refreshComboInNodes();
|
||||
}
|
||||
},
|
||||
|
||||
".nu-manager-stop": {
|
||||
click: () => {
|
||||
api.fetchApi('/manager/queue/reset');
|
||||
infoToast('Cancel', 'Remaining tasks will stop after completing the current task.');
|
||||
}
|
||||
},
|
||||
|
||||
".nu-manager-back": {
|
||||
click: (e) => {
|
||||
this.close()
|
||||
manager_instance.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
Object.keys(eventsMap).forEach(selector => {
|
||||
const target = this.element.querySelector(selector);
|
||||
if (target) {
|
||||
const events = eventsMap[selector];
|
||||
if (events) {
|
||||
Object.keys(events).forEach(type => {
|
||||
target.addEventListener(type, events[type]);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ===========================================================================================
|
||||
|
||||
initGrid() {
|
||||
const container = this.element.querySelector(".nu-manager-grid");
|
||||
const grid = new TG.Grid(container);
|
||||
this.grid = grid;
|
||||
|
||||
this.flyover = createFlyover(container, { context: this });
|
||||
|
||||
grid.bind('onUpdated', (e, d) => {
|
||||
this.ui.showStatus(`${grid.viewRows.length.toLocaleString()} installed packages`);
|
||||
|
||||
});
|
||||
|
||||
grid.bind('onSelectChanged', (e, changes) => {
|
||||
this.renderSelected();
|
||||
});
|
||||
|
||||
grid.bind("onColumnWidthChanged", (e, columnItem) => {
|
||||
storeColumnWidth(gridId, columnItem)
|
||||
});
|
||||
|
||||
grid.bind('onClick', (e, d) => {
|
||||
const { rowItem } = d;
|
||||
const target = d.e.target;
|
||||
const mode = target.getAttribute("mode");
|
||||
|
||||
if (mode === "install") {
|
||||
this.installModels([rowItem], target);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode === "uninstall") {
|
||||
this.uninstallModels([rowItem], target);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle click on usage count
|
||||
if (d.columnItem.id === "used_in_count" && rowItem.used_in_count > 0) {
|
||||
this.showUsageDetails(rowItem);
|
||||
return;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
grid.setOption({
|
||||
theme: 'dark',
|
||||
|
||||
selectVisible: true,
|
||||
selectMultiple: true,
|
||||
selectAllVisible: true,
|
||||
|
||||
textSelectable: true,
|
||||
scrollbarRound: true,
|
||||
|
||||
frozenColumn: 1,
|
||||
rowNotFound: "No Results",
|
||||
|
||||
rowHeight: 40,
|
||||
bindWindowResize: true,
|
||||
bindContainerResize: true,
|
||||
|
||||
cellResizeObserver: (rowItem, columnItem) => {
|
||||
const autoHeightColumns = ['name', 'description'];
|
||||
return autoHeightColumns.includes(columnItem.id)
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
renderGrid() {
|
||||
|
||||
// update theme
|
||||
const colorPalette = this.app.ui.settings.settingsValues['Comfy.ColorPalette'];
|
||||
Array.from(this.element.classList).forEach(cn => {
|
||||
if (cn.startsWith("nu-manager-")) {
|
||||
this.element.classList.remove(cn);
|
||||
}
|
||||
});
|
||||
this.element.classList.add(`nu-manager-${colorPalette}`);
|
||||
|
||||
const options = {
|
||||
theme: colorPalette === "light" ? "" : "dark"
|
||||
};
|
||||
|
||||
const rows = this.modelList || [];
|
||||
|
||||
const columns = [{
|
||||
id: 'title',
|
||||
name: 'Title',
|
||||
width: 200,
|
||||
minWidth: 100,
|
||||
maxWidth: 500,
|
||||
classMap: 'nu-pack-name',
|
||||
formatter: function (name, rowItem, columnItem, cellNode) {
|
||||
return `<a href=${rowItem.reference} target="_blank"><b>${name}</b></a>`;
|
||||
}
|
||||
}, {
|
||||
id: 'used_in_count',
|
||||
name: 'Used in',
|
||||
width: 100,
|
||||
formatter: function (usedCount, rowItem, columnItem) {
|
||||
if (!usedCount || usedCount === 0) {
|
||||
return '0';
|
||||
}
|
||||
const plural = usedCount > 1 ? 's' : '';
|
||||
return `<div class="cn-pack-nodes" style="cursor: pointer;">${usedCount} workflow${plural}</div>`;
|
||||
}
|
||||
}, {
|
||||
id: 'action',
|
||||
name: 'Action',
|
||||
width: 160,
|
||||
minWidth: 140,
|
||||
maxWidth: 200,
|
||||
sortable: false,
|
||||
align: 'center',
|
||||
formatter: function (action, rowItem, columnItem) {
|
||||
// Only show uninstall button for installed packages
|
||||
if (rowItem.originalData && rowItem.originalData.state && rowItem.originalData.state !== "not-installed") {
|
||||
return `<div class="cn-install-buttons"><button class="nu-btn-uninstall" mode="uninstall">Uninstall</button></div>`;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}];
|
||||
|
||||
restoreColumnWidth(gridId, columns);
|
||||
|
||||
this.grid.setData({
|
||||
options,
|
||||
rows,
|
||||
columns
|
||||
});
|
||||
|
||||
this.grid.render();
|
||||
|
||||
}
|
||||
|
||||
updateGrid() {
|
||||
if (this.grid) {
|
||||
this.grid.update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
showUsageDetails(rowItem) {
|
||||
const workflowList = rowItem.workflowDetails;
|
||||
if (!workflowList || workflowList.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let titleHtml = `<div class="cn-nodes-pack">${rowItem.title}</div>`;
|
||||
|
||||
const list = [];
|
||||
list.push(`<div class="cn-nodes-list">`);
|
||||
|
||||
workflowList.forEach((workflow, i) => {
|
||||
list.push(`<div class="cn-nodes-row">`);
|
||||
list.push(`<div class="cn-nodes-sn">${i + 1}</div>`);
|
||||
list.push(`<div class="cn-nodes-name">${workflow.filename}</div>`);
|
||||
list.push(`<div class="cn-nodes-details">${workflow.nodeCount} node${workflow.nodeCount > 1 ? 's' : ''}</div>`);
|
||||
list.push(`</div>`);
|
||||
});
|
||||
|
||||
list.push("</div>");
|
||||
const bodyHtml = list.join("");
|
||||
|
||||
this.flyover.show(titleHtml, bodyHtml);
|
||||
}
|
||||
|
||||
renderSelected() {
|
||||
const selectedList = this.grid.getSelectedRows();
|
||||
if (!selectedList.length) {
|
||||
this.ui.showSelection("");
|
||||
return;
|
||||
}
|
||||
|
||||
const installedSelected = selectedList.filter(item =>
|
||||
item.originalData && item.originalData.state && item.originalData.state !== "not-installed"
|
||||
);
|
||||
|
||||
if (installedSelected.length === 0) {
|
||||
this.ui.showSelection(`<span>Selected <b>${selectedList.length}</b> packages (none can be uninstalled)</span>`);
|
||||
return;
|
||||
}
|
||||
|
||||
this.selectedModels = installedSelected;
|
||||
|
||||
this.ui.showSelection(`
|
||||
<div class="nu-selected-buttons">
|
||||
<span>Selected <b>${installedSelected.length}</b> installed packages</span>
|
||||
<button class="nu-btn-uninstall" mode="uninstall">Uninstall Selected</button>
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
|
||||
// ===========================================================================================
|
||||
|
||||
async installModels(list, btn) {
|
||||
let stats = await api.fetchApi('/manager/queue/status');
|
||||
|
||||
stats = await stats.json();
|
||||
if (stats.is_processing) {
|
||||
customAlert(`[ComfyUI-Manager] There are already tasks in progress. Please try again after it is completed. (${stats.done_count}/${stats.total_count})`);
|
||||
return;
|
||||
}
|
||||
|
||||
btn.classList.add("nu-btn-loading");
|
||||
this.ui.showError("");
|
||||
|
||||
let needRefresh = false;
|
||||
let errorMsg = "";
|
||||
|
||||
await api.fetchApi('/manager/queue/reset');
|
||||
|
||||
let target_items = [];
|
||||
|
||||
for (const item of list) {
|
||||
this.grid.scrollRowIntoView(item);
|
||||
target_items.push(item);
|
||||
|
||||
|
||||
this.ui.showStatus(`Install ${item.name} ...`);
|
||||
|
||||
const data = item.originalData;
|
||||
data.ui_id = item.hash;
|
||||
|
||||
const res = await api.fetchApi(`/manager/queue/install_model`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (res.status != 200) {
|
||||
errorMsg = `'${item.name}': `;
|
||||
|
||||
if (res.status == 403) {
|
||||
errorMsg += `This action is not allowed with this security level configuration.\n`;
|
||||
} else {
|
||||
errorMsg += await res.text() + '\n';
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.install_context = { btn: btn, targets: target_items };
|
||||
|
||||
if (errorMsg) {
|
||||
this.ui.showError(errorMsg);
|
||||
show_message("[Installation Errors]\n" + errorMsg);
|
||||
|
||||
// reset
|
||||
for (let k in target_items) {
|
||||
const item = target_items[k];
|
||||
this.grid.updateCell(item, "installed");
|
||||
}
|
||||
}
|
||||
else {
|
||||
await api.fetchApi('/manager/queue/start');
|
||||
this.ui.showStop();
|
||||
showTerminal();
|
||||
}
|
||||
}
|
||||
|
||||
async uninstallModels(list, btn) {
|
||||
btn.classList.add("nu-btn-loading");
|
||||
this.ui.showError("");
|
||||
|
||||
const result = await uninstallNodes(list, {
|
||||
title: list.length === 1 ? list[0].title || list[0].name : `${list.length} custom nodes`,
|
||||
channel: 'default',
|
||||
mode: 'default',
|
||||
onProgress: (msg) => {
|
||||
this.showStatus(msg);
|
||||
},
|
||||
onError: (errorMsg) => {
|
||||
this.showError(errorMsg);
|
||||
},
|
||||
onSuccess: (targets) => {
|
||||
this.showStatus(`Uninstalled ${targets.length} custom node(s) successfully`);
|
||||
this.showMessage(`To apply the uninstalled custom nodes, please restart ComfyUI and refresh browser.`, "red");
|
||||
// Update the grid to reflect changes
|
||||
for (let item of targets) {
|
||||
if (item.originalData) {
|
||||
item.originalData.state = "not-installed";
|
||||
}
|
||||
this.grid.updateRow(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (result.success) {
|
||||
this.showStop();
|
||||
}
|
||||
|
||||
btn.classList.remove("nu-btn-loading");
|
||||
}
|
||||
|
||||
async onQueueStatus(event) {
|
||||
let self = NodeUsageAnalyzer.instance;
|
||||
|
||||
if (event.detail.status == 'in_progress' && (event.detail.ui_target == 'model_manager' || event.detail.ui_target == 'nodepack_manager')) {
|
||||
const hash = event.detail.target;
|
||||
|
||||
const item = self.grid.getRowItemBy("hash", hash);
|
||||
|
||||
if (item) {
|
||||
item.refresh = true;
|
||||
self.grid.setRowSelected(item, false);
|
||||
item.selectable = false;
|
||||
self.grid.updateRow(item);
|
||||
}
|
||||
}
|
||||
else if (event.detail.status == 'done') {
|
||||
self.hideStop();
|
||||
self.onQueueCompleted(event.detail);
|
||||
}
|
||||
}
|
||||
|
||||
async onQueueCompleted(info) {
|
||||
let result = info.model_result || info.nodepack_result;
|
||||
|
||||
if (!result || result.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let self = NodeUsageAnalyzer.instance;
|
||||
|
||||
if (!self.install_context) {
|
||||
return;
|
||||
}
|
||||
|
||||
let btn = self.install_context.btn;
|
||||
|
||||
self.hideLoading();
|
||||
btn.classList.remove("nu-btn-loading");
|
||||
|
||||
let errorMsg = "";
|
||||
|
||||
for (let hash in result) {
|
||||
let v = result[hash];
|
||||
|
||||
if (v != 'success' && v != 'skip')
|
||||
errorMsg += v + '\n';
|
||||
}
|
||||
|
||||
for (let k in self.install_context.targets) {
|
||||
let item = self.install_context.targets[k];
|
||||
if (info.model_result) {
|
||||
self.grid.updateCell(item, "installed");
|
||||
} else if (info.nodepack_result) {
|
||||
// Handle uninstall completion
|
||||
if (item.originalData) {
|
||||
item.originalData.state = "not-installed";
|
||||
}
|
||||
self.grid.updateRow(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (errorMsg) {
|
||||
self.showError(errorMsg);
|
||||
show_message("Operation Error:\n" + errorMsg);
|
||||
} else {
|
||||
if (info.model_result) {
|
||||
self.showStatus(`Install ${Object.keys(result).length} models successfully`);
|
||||
self.showRefresh();
|
||||
self.showMessage(`To apply the installed model, please click the 'Refresh' button.`, "red");
|
||||
} else if (info.nodepack_result) {
|
||||
self.showStatus(`Uninstall ${Object.keys(result).length} custom node(s) successfully`);
|
||||
self.showMessage(`To apply the uninstalled custom nodes, please restart ComfyUI and refresh browser.`, "red");
|
||||
}
|
||||
}
|
||||
|
||||
infoToast('Tasks done', `[ComfyUI-Manager] All tasks in the queue have been completed.\n${info.done_count}/${info.total_count}`);
|
||||
self.install_context = undefined;
|
||||
}
|
||||
|
||||
getModelList(models) {
|
||||
const typeMap = new Map();
|
||||
const baseMap = new Map();
|
||||
|
||||
models.forEach((item, i) => {
|
||||
const { type, base, name, reference, installed } = item;
|
||||
// CRITICAL FIX: Do NOT overwrite originalData - it contains the needed state field!
|
||||
item.size = sizeToBytes(item.size);
|
||||
item.hash = md5(name + reference);
|
||||
|
||||
if (installed === "True") {
|
||||
item.selectable = false;
|
||||
}
|
||||
|
||||
typeMap.set(type, type);
|
||||
baseMap.set(base, base);
|
||||
|
||||
});
|
||||
|
||||
const typeList = [];
|
||||
typeMap.forEach(type => {
|
||||
typeList.push({
|
||||
label: type,
|
||||
value: type
|
||||
});
|
||||
});
|
||||
typeList.sort((a, b) => {
|
||||
const au = a.label.toUpperCase();
|
||||
const bu = b.label.toUpperCase();
|
||||
if (au !== bu) {
|
||||
return au > bu ? 1 : -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
this.typeList = [{
|
||||
label: "All",
|
||||
value: ""
|
||||
}].concat(typeList);
|
||||
|
||||
|
||||
const baseList = [];
|
||||
baseMap.forEach(base => {
|
||||
baseList.push({
|
||||
label: base,
|
||||
value: base
|
||||
});
|
||||
});
|
||||
baseList.sort((a, b) => {
|
||||
const au = a.label.toUpperCase();
|
||||
const bu = b.label.toUpperCase();
|
||||
if (au !== bu) {
|
||||
return au > bu ? 1 : -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
this.baseList = [{
|
||||
label: "All",
|
||||
value: ""
|
||||
}].concat(baseList);
|
||||
|
||||
return models;
|
||||
}
|
||||
|
||||
// ===========================================================================================
|
||||
|
||||
async loadData() {
|
||||
|
||||
this.showLoading();
|
||||
this.showStatus(`Analyzing node usage ...`);
|
||||
|
||||
const mode = manager_instance.datasrc_combo.value;
|
||||
|
||||
const nodeListRes = await fetchData(`/customnode/getlist?mode=${mode}&skip_update=true`);
|
||||
if (nodeListRes.error) {
|
||||
this.showError("Failed to get custom node list.");
|
||||
this.hideLoading();
|
||||
return;
|
||||
}
|
||||
|
||||
const { channel, node_packs } = nodeListRes.data;
|
||||
delete node_packs['comfyui-manager'];
|
||||
this.installed_custom_node_packs = node_packs;
|
||||
|
||||
// Use the consolidated workflow analysis utility
|
||||
const result = await analyzeWorkflowUsage(node_packs);
|
||||
|
||||
if (!result.success) {
|
||||
if (result.error.toString().includes('204')) {
|
||||
this.showMessage("No workflows were found for analysis.");
|
||||
} else {
|
||||
this.showError(result.error);
|
||||
this.hideLoading();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Transform node_packs into models format - ONLY INSTALLED PACKAGES
|
||||
const models = [];
|
||||
|
||||
Object.keys(node_packs).forEach((packKey, index) => {
|
||||
const pack = node_packs[packKey];
|
||||
|
||||
// Only include installed packages (filter out "not-installed" packages)
|
||||
if (pack.state === "not-installed") {
|
||||
return; // Skip non-installed packages
|
||||
}
|
||||
|
||||
const usedCount = result.usageMap?.get(packKey) || 0;
|
||||
const workflowDetails = result.workflowDetailsMap?.get(packKey) || [];
|
||||
|
||||
models.push({
|
||||
title: pack.title || packKey,
|
||||
reference: pack.reference || pack.files?.[0] || '#',
|
||||
used_in_count: usedCount,
|
||||
workflowDetails: workflowDetails,
|
||||
name: packKey,
|
||||
originalData: pack
|
||||
});
|
||||
});
|
||||
|
||||
// Sort by usage count (descending) then by title
|
||||
models.sort((a, b) => {
|
||||
if (b.used_in_count !== a.used_in_count) {
|
||||
return b.used_in_count - a.used_in_count;
|
||||
}
|
||||
return a.title.localeCompare(b.title);
|
||||
});
|
||||
|
||||
this.modelList = this.getModelList(models);
|
||||
|
||||
this.renderGrid();
|
||||
|
||||
this.hideLoading();
|
||||
|
||||
}
|
||||
|
||||
// ===========================================================================================
|
||||
|
||||
showSelection(msg) {
|
||||
this.element.querySelector(".nu-manager-selection").innerHTML = msg;
|
||||
}
|
||||
|
||||
showError(err) {
|
||||
this.showMessage(err, "red");
|
||||
}
|
||||
|
||||
showMessage(msg, color) {
|
||||
if (color) {
|
||||
msg = `<font color="${color}">${msg}</font>`;
|
||||
}
|
||||
this.element.querySelector(".nu-manager-message").innerHTML = msg;
|
||||
}
|
||||
|
||||
showStatus(msg, color) {
|
||||
if (color) {
|
||||
msg = `<font color="${color}">${msg}</font>`;
|
||||
}
|
||||
this.element.querySelector(".nu-manager-status").innerHTML = msg;
|
||||
}
|
||||
|
||||
showLoading() {
|
||||
// this.setDisabled(true);
|
||||
if (this.grid) {
|
||||
this.grid.showLoading();
|
||||
this.grid.showMask({
|
||||
opacity: 0.05
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
hideLoading() {
|
||||
// this.setDisabled(false);
|
||||
if (this.grid) {
|
||||
this.grid.hideLoading();
|
||||
this.grid.hideMask();
|
||||
}
|
||||
}
|
||||
|
||||
setDisabled(disabled) {
|
||||
const $close = this.element.querySelector(".nu-manager-close");
|
||||
const $refresh = this.element.querySelector(".nu-manager-refresh");
|
||||
const $stop = this.element.querySelector(".nu-manager-stop");
|
||||
|
||||
const list = [
|
||||
".nu-manager-header input",
|
||||
".nu-manager-header select",
|
||||
".nu-manager-footer button",
|
||||
".nu-manager-selection button"
|
||||
].map(s => {
|
||||
return Array.from(this.element.querySelectorAll(s));
|
||||
})
|
||||
.flat()
|
||||
.filter(it => {
|
||||
return it !== $close && it !== $refresh && it !== $stop;
|
||||
});
|
||||
|
||||
list.forEach($elem => {
|
||||
if (disabled) {
|
||||
$elem.setAttribute("disabled", "disabled");
|
||||
} else {
|
||||
$elem.removeAttribute("disabled");
|
||||
}
|
||||
});
|
||||
|
||||
Array.from(this.element.querySelectorAll(".nu-btn-loading")).forEach($elem => {
|
||||
$elem.classList.remove("nu-btn-loading");
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
showRefresh() {
|
||||
this.element.querySelector(".nu-manager-refresh").style.display = "block";
|
||||
}
|
||||
|
||||
showStop() {
|
||||
this.element.querySelector(".nu-manager-stop").style.display = "block";
|
||||
}
|
||||
|
||||
hideStop() {
|
||||
this.element.querySelector(".nu-manager-stop").style.display = "none";
|
||||
}
|
||||
|
||||
setKeywords(keywords = "") {
|
||||
this.keywords = keywords;
|
||||
this.element.querySelector(".nu-manager-keywords").value = keywords;
|
||||
}
|
||||
|
||||
show(sortMode) {
|
||||
this.element.style.display = "flex";
|
||||
this.setKeywords("");
|
||||
this.showSelection("");
|
||||
this.showMessage("");
|
||||
this.loadData();
|
||||
}
|
||||
|
||||
close() {
|
||||
this.element.style.display = "none";
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,75 @@
|
||||
{
|
||||
"custom_nodes": [
|
||||
{
|
||||
"author": "cosmicbuffalo",
|
||||
"title": "comfyui-mobile-frontend",
|
||||
"reference": "https://github.com/cosmicbuffalo/comfyui-mobile-frontend",
|
||||
"files": [
|
||||
"https://github.com/cosmicbuffalo/comfyui-mobile-frontend"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "An experimental dedicated mobile-first frontend for ComfyUI."
|
||||
},
|
||||
{
|
||||
"author": "tdrminglin",
|
||||
"title": "Comfyui-hymotionbridge",
|
||||
"reference": "https://github.com/tdrminglin/Comfyui-hymotionbridge",
|
||||
"files": [
|
||||
"https://github.com/tdrminglin/Comfyui-hymotionbridge"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "NODES: HYMotionToNLFBridge, HYMotionToSCAILBridge"
|
||||
},
|
||||
{
|
||||
"author": "joe002",
|
||||
"title": "comfyui-rtx-remix [UNSAFE]",
|
||||
"reference": "https://github.com/joe002/comfyui-rtx-remix",
|
||||
"files": [
|
||||
"https://github.com/joe002/comfyui-rtx-remix"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "RTX Remix texture pipeline integration nodes for ComfyUI[w/This nodepack contains a path traversal vulnerability.]"
|
||||
},
|
||||
{
|
||||
"author": "NakanoSanku",
|
||||
"title": "ComfyUI-Gemini [NAME CONFLICT]",
|
||||
"reference": "https://github.com/NakanoSanku/ComfyUI-Gemini",
|
||||
"files": [
|
||||
"https://github.com/NakanoSanku/ComfyUI-Gemini"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom ComfyUI nodes for Google Gemini AI with text generation and image generation capabilities using the Python SDK."
|
||||
},
|
||||
{
|
||||
"author": "Saganaki22",
|
||||
"title": "ComfyUI-NovaSR",
|
||||
"reference": "https://github.com/Saganaki22/ComfyUI-NovaSR",
|
||||
"files": [
|
||||
"https://github.com/Saganaki22/ComfyUI-NovaSR"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI node for NovaSR - Ultra-fast audio super resolution (3600x realtime, 50KB model)"
|
||||
},
|
||||
{
|
||||
"author": "GokuHiki",
|
||||
"title": "ComfyUI-Goku-Tools",
|
||||
"reference": "https://github.com/GokuHiki/ComfyUI-Goku-Tools",
|
||||
"files": [
|
||||
"https://github.com/GokuHiki/ComfyUI-Goku-Tools"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI custom nodes including FirstNonFalse utility. (Description by CC)"
|
||||
},
|
||||
{
|
||||
"author": "endman100",
|
||||
"title": "ComfyUI_tensor_script [WIP]",
|
||||
"reference": "https://github.com/endman100/ComfyUI_tensor_script",
|
||||
"files": [
|
||||
"https://github.com/endman100/ComfyUI_tensor_script"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Utility nodes for tensor manipulation including squeeze, unsqueeze, and shape operations. (Description by CC)\nNOTE: The files in the repo are not organized."
|
||||
},
|
||||
{
|
||||
"author": "CarlMarkswx",
|
||||
"title": "ComfyUI-Mirror-Download [UNSAFE]",
|
||||
@ -10220,16 +10290,6 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "Nodes:CLIPTextEncodeAndEnhance.\nNOTE:Translation:This is a wrapper that simply makes it easy to install an existing node via git."
|
||||
},
|
||||
{
|
||||
"author": "umisetokikaze",
|
||||
"title": "comfyui_mergekit [WIP]",
|
||||
"reference": "https://github.com/umisetokikaze/comfyui_mergekit",
|
||||
"files": [
|
||||
"https://github.com/umisetokikaze/comfyui_mergekit"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Nodes:DefineSaveName, SetModels, get_skip, LoadLR, LoadTarget, SetTokenizer, Merge, SetLayer, SetModels"
|
||||
},
|
||||
{
|
||||
"author": "Video3DGenResearch",
|
||||
"title": "ComfyUI Batch Input Node",
|
||||
|
||||
@ -2127,6 +2127,14 @@
|
||||
"title_aux": "ComfyUI-GoddessLabs-NodePack"
|
||||
}
|
||||
],
|
||||
"https://github.com/GokuHiki/ComfyUI-Goku-Tools": [
|
||||
[
|
||||
"FirstNonFalse"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-Goku-Tools"
|
||||
}
|
||||
],
|
||||
"https://github.com/Goldlionren/ComfyUI-CleanSlate": [
|
||||
[
|
||||
"CleanSlateCleanup"
|
||||
@ -4295,6 +4303,14 @@
|
||||
"title_aux": "ComfyUI Port for Google's Prompt-to-Prompt"
|
||||
}
|
||||
],
|
||||
"https://github.com/Saganaki22/ComfyUI-NovaSR": [
|
||||
[
|
||||
"NovaSR"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-NovaSR"
|
||||
}
|
||||
],
|
||||
"https://github.com/Saganaki22/ComfyUI-ytdl_nodes": [
|
||||
[
|
||||
"YTDLDownloader",
|
||||
@ -7181,6 +7197,13 @@
|
||||
"MaskComposite",
|
||||
"MaskPreview",
|
||||
"MaskToImage",
|
||||
"MeshyAnimateModelNode",
|
||||
"MeshyImageToModelNode",
|
||||
"MeshyMultiImageToModelNode",
|
||||
"MeshyRefineNode",
|
||||
"MeshyRigModelNode",
|
||||
"MeshyTextToModelNode",
|
||||
"MeshyTextureNode",
|
||||
"MinimaxHailuoVideoNode",
|
||||
"MinimaxImageToVideoNode",
|
||||
"MinimaxSubjectToVideoNode",
|
||||
@ -8089,6 +8112,20 @@
|
||||
"title_aux": "ComfyUI-augmentation"
|
||||
}
|
||||
],
|
||||
"https://github.com/endman100/ComfyUI_tensor_script": [
|
||||
[
|
||||
"LatentSqueeze",
|
||||
"LatentUnsqueeze",
|
||||
"TensorEmpty",
|
||||
"TensorGetShape",
|
||||
"TensorShowShape",
|
||||
"TensorSqueeze",
|
||||
"TensorUnsqueeze"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_tensor_script [WIP]"
|
||||
}
|
||||
],
|
||||
"https://github.com/enlo/ComfyUI-CheckpointSettings": [
|
||||
[
|
||||
"CheckPointSettingsListMerger",
|
||||
@ -9549,6 +9586,20 @@
|
||||
"title_aux": "jn_node_suite_comfyui [WIP]"
|
||||
}
|
||||
],
|
||||
"https://github.com/joe002/comfyui-rtx-remix": [
|
||||
[
|
||||
"RTXRemixBatchLoader",
|
||||
"RTXRemixGeneratePBR",
|
||||
"RTXRemixHashLookup",
|
||||
"RTXRemixIterateTextures",
|
||||
"RTXRemixLoadCapture",
|
||||
"RTXRemixProjectInfo",
|
||||
"RTXRemixSaveToMod"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-rtx-remix [UNSAFE]"
|
||||
}
|
||||
],
|
||||
"https://github.com/jonathan-bryant/ComfyUI-ImageStraightener": [
|
||||
[
|
||||
"AutoStraightenImage"
|
||||
@ -12524,6 +12575,7 @@
|
||||
"ImageBlendByMask",
|
||||
"Image_Color_Noise",
|
||||
"ModifyMask",
|
||||
"SU_LoadImagePath",
|
||||
"SamplingParameters",
|
||||
"SystemMessagePresets",
|
||||
"TextEncodeFlux2SystemPrompt",
|
||||
@ -12680,21 +12732,19 @@
|
||||
],
|
||||
"https://github.com/sprited-ai/sprited-comfyui-nodes": [
|
||||
[
|
||||
"FlattenImageList",
|
||||
"LoopExtractorNodeV2",
|
||||
"LoopMomentumNode",
|
||||
"LoopTrimNode",
|
||||
"LoopExtractorNodeV3",
|
||||
"MakeGrid",
|
||||
"PixelRGBStats",
|
||||
"PreviewVideo",
|
||||
"ShotSplitByCutScore",
|
||||
"SliceBatch",
|
||||
"SliceLatents",
|
||||
"SpriteDXAntiCorruptionV1",
|
||||
"SpriteDX_ParseInt",
|
||||
"SpritedMakeGrid",
|
||||
"URLToVideo",
|
||||
"VideoDownloader",
|
||||
"VideoEvenShotSplitter",
|
||||
"VideoShotSplitter",
|
||||
"VideoShotSplitterV0",
|
||||
"VideoShotSplitterV2",
|
||||
"VideoShotSplitterV3"
|
||||
"VideoEvenShotSplitter"
|
||||
],
|
||||
{
|
||||
"title_aux": "Sprited ComfyUI Nodes [WIP]"
|
||||
@ -13093,6 +13143,15 @@
|
||||
"title_aux": "ComfyUI_SceneSplitter"
|
||||
}
|
||||
],
|
||||
"https://github.com/tdrminglin/Comfyui-hymotionbridge": [
|
||||
[
|
||||
"HYMotionToNLFBridge",
|
||||
"HYMotionToSCAILBridge"
|
||||
],
|
||||
{
|
||||
"title_aux": "Comfyui-hymotionbridge"
|
||||
}
|
||||
],
|
||||
"https://github.com/techidsk/comfyui_molook_nodes": [
|
||||
[
|
||||
"ImageOutpaintPadding(Molook)",
|
||||
@ -13446,27 +13505,6 @@
|
||||
"title_aux": "ComfyUI_u5_EasyScripter [UNSAFE]"
|
||||
}
|
||||
],
|
||||
"https://github.com/umisetokikaze/comfyui_mergekit": [
|
||||
[
|
||||
"DefineSaveName",
|
||||
"LoadLR",
|
||||
"LoadTarget",
|
||||
"Merge",
|
||||
"SetLayer",
|
||||
"SetModels",
|
||||
"SetTokenizer",
|
||||
"create models list",
|
||||
"get skip layers",
|
||||
"get_skip",
|
||||
"load and save tokenizer",
|
||||
"loding llm model",
|
||||
"loding target model",
|
||||
"str to parsed layers"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui_mergekit [WIP]"
|
||||
}
|
||||
],
|
||||
"https://github.com/unanan/ComfyUI-Dist": [
|
||||
[
|
||||
"LoadImageFromLAN",
|
||||
@ -14099,6 +14137,7 @@
|
||||
"MultiplyNode",
|
||||
"NumberNode",
|
||||
"OutpaintingPadNode",
|
||||
"PerfectPixelNode",
|
||||
"PrependTagsNode",
|
||||
"PrintAnyNode",
|
||||
"PrintImageNode",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,25 @@
|
||||
{
|
||||
"custom_nodes": [
|
||||
{
|
||||
"author": "Wladimir Palant",
|
||||
"title": "image-resize-comfyui [REMOVED]",
|
||||
"reference": "https://github.com/ussoewwin/image_resize_comfyui",
|
||||
"files": [
|
||||
"https://github.com/ussoewwin/image_resize_comfyui"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Advanced image resizing node for ComfyUI with aspect ratio preservation and mask support"
|
||||
},
|
||||
{
|
||||
"author": "umisetokikaze",
|
||||
"title": "comfyui_mergekit [REMOVED]",
|
||||
"reference": "https://github.com/umisetokikaze/comfyui_mergekit",
|
||||
"files": [
|
||||
"https://github.com/umisetokikaze/comfyui_mergekit"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Nodes:DefineSaveName, SetModels, get_skip, LoadLR, LoadTarget, SetTokenizer, Merge, SetLayer, SetModels"
|
||||
},
|
||||
{
|
||||
"author": "LSDJesus",
|
||||
"title": "ComfyUI-Luna-Collection [REMOVED]",
|
||||
|
||||
@ -1,5 +1,240 @@
|
||||
{
|
||||
"custom_nodes": [
|
||||
{
|
||||
"author": "loz2754",
|
||||
"title": "AUN ComfyUI Nodes",
|
||||
"id": "aun-comfyui-nodes",
|
||||
"reference": "https://github.com/loz2754/AUN-ComfyUI-Nodes",
|
||||
"files": [
|
||||
"https://github.com/loz2754/AUN-ComfyUI-Nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A collection of workflow helper nodes focused on organization + control (bypass/mute/collapse/group control), prompt/text utilities, file/path helpers, and image/video save helpers (optional VHS integration)."
|
||||
},
|
||||
{
|
||||
"author": "SergPoletaev",
|
||||
"title": "ComfyUI-SPoletNodes",
|
||||
"id": "ComfyUI-SPoletNodes",
|
||||
"reference": "https://github.com/SergPoletaev/ComfyUI-SPoletNodes",
|
||||
"files": [
|
||||
"https://github.com/SergPoletaev/ComfyUI-SPoletNodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom nodes for image preview and saving"
|
||||
},
|
||||
{
|
||||
"author": "capitan01R",
|
||||
"title": "ComfyUI-CapitanZiT-Scheduler",
|
||||
"reference": "https://github.com/capitan01R/ComfyUI-CapitanZiT-Scheduler",
|
||||
"files": [
|
||||
"https://github.com/capitan01R/ComfyUI-CapitanZiT-Scheduler"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A lightweight ComfyUI custom scheduler & sigma generator for Z-Image-Turbo. Delivers a stable linear sigma schedule (1.0 → 0.0) for rectified-flow/flow-matching, boosting few-step generation (8-9 steps) with superior consistency, reduced noise, and full compatibility with the model's distilled pipeline."
|
||||
},
|
||||
{
|
||||
"author": "joe002",
|
||||
"title": "comfyui-deterministic-nodes",
|
||||
"reference": "https://github.com/joe002/comfyui-deterministic-nodes",
|
||||
"files": [
|
||||
"https://github.com/joe002/comfyui-deterministic-nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Batch-invariant inference nodes for guaranteed reproducibility in ComfyUI"
|
||||
},
|
||||
{
|
||||
"author": "joe002",
|
||||
"title": "comfyui-conduit-optimizer",
|
||||
"reference": "https://github.com/joe002/comfyui-conduit-optimizer",
|
||||
"files": [
|
||||
"https://github.com/joe002/comfyui-conduit-optimizer"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Non-linear inference optimization for ComfyUI: 4-tier VRAM, speculative generation, precision routing"
|
||||
},
|
||||
{
|
||||
"author": "joe002",
|
||||
"title": "comfyui-rtx4090-nodes",
|
||||
"reference": "https://github.com/joe002/comfyui-rtx4090-nodes",
|
||||
"files": [
|
||||
"https://github.com/joe002/comfyui-rtx4090-nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "High-performance ComfyUI nodes optimized for RTX 4090: batch processing, memory management, GPU monitoring"
|
||||
},
|
||||
|
||||
{
|
||||
"author": "tackcrypto1031",
|
||||
"title": "tk_comfyui_view_and_light",
|
||||
"reference": "https://github.com/tackcrypto1031/tk_comfyui_view_and_light",
|
||||
"files": [
|
||||
"https://github.com/tackcrypto1031/tk_comfyui_view_and_light"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "TK View and Light: A ComfyUI node for 3D camera and lighting control"
|
||||
},
|
||||
{
|
||||
"author": "XelaNull",
|
||||
"title": "ComfyUI-MobileFriendly",
|
||||
"reference": "https://github.com/XelaNull/ComfyUI-MobileFriendly",
|
||||
"files": [
|
||||
"https://github.com/XelaNull/ComfyUI-MobileFriendly"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Comprehensive mobile UI enhancement for ComfyUI that transforms the desktop-focused interface into a touch-friendly experience optimized for iPhone, iPad, and Android devices."
|
||||
},
|
||||
{
|
||||
"author": "aadityamundhalia",
|
||||
"title": "ComfyUI-ollama-aditya",
|
||||
"reference": "https://github.com/aadityamundhalia/ComfyUI-ollama-aditya",
|
||||
"files": [
|
||||
"https://github.com/aadityamundhalia/ComfyUI-ollama-aditya"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom ComfyUI node for integrating Ollama LLMs into your image generation workflows."
|
||||
},
|
||||
{
|
||||
"author": "maximilianwicen",
|
||||
"title": "ComfyUI-MaxTools",
|
||||
"reference": "https://github.com/maximilianwicen/ComfyUI-MaxTools",
|
||||
"files": [
|
||||
"https://github.com/maximilianwicen/ComfyUI-MaxTools"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A small collection of custom nodes for ComfyUI, featuring Max Quick Image Size node for image-to-image or image-to-video workflows. (Description by CC)"
|
||||
},
|
||||
{
|
||||
"author": "bhhtr12",
|
||||
"title": "ComfyUI-ollama-stop",
|
||||
"reference": "https://github.com/bhhtr12/ComfyUI-ollama-stop",
|
||||
"files": [
|
||||
"https://github.com/bhhtr12/ComfyUI-ollama-stop"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Passthrough node that instantly unloads any running ollama model mid workflow. No API calls, just accepts plain string as a model name and executes 'ollama stop <model>' command in your system."
|
||||
},
|
||||
{
|
||||
"author": "DemonAlone",
|
||||
"title": "SimpeStringGenerator_ComfyUI",
|
||||
"reference": "https://github.com/DemonAlone/SimpeStringGenerator_ComfyUI",
|
||||
"files": [
|
||||
"https://github.com/DemonAlone/SimpeStringGenerator_ComfyUI"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A collection of nodes that provide dynamic dropdown selectors for Samplers, Schedulers, Checkpoints, and Diffusion Models, outputting a comma-separated string for use in XY plots."
|
||||
},
|
||||
{
|
||||
"author": "tabisheva",
|
||||
"title": "comfyui-segs-profile",
|
||||
"reference": "https://github.com/tabisheva/comfyui-segs-profile",
|
||||
"files": [
|
||||
"https://github.com/tabisheva/comfyui-segs-profile"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A tiny ComfyUI custom node that detects whether a face is in profile using SEGS eye detections."
|
||||
},
|
||||
{
|
||||
"author": "QuackPhuc",
|
||||
"title": "ComfyUI-FisheyeTransform",
|
||||
"reference": "https://github.com/QuackPhuc/ComfyUI-FisheyeTransform",
|
||||
"files": [
|
||||
"https://github.com/QuackPhuc/ComfyUI-FisheyeTransform"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom nodes for handling fisheye camera distortion in ComfyUI inpainting workflows."
|
||||
},
|
||||
{
|
||||
"author": "1x1r",
|
||||
"title": "comfyui-upscale-by-model",
|
||||
"reference": "https://github.com/1x1r/comfyui-upscale-by-model",
|
||||
"files": [
|
||||
"https://github.com/1x1r/comfyui-upscale-by-model"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "This custom node allow upscaling an image by a factor using a model."
|
||||
},
|
||||
{
|
||||
"author": "RCAKangle",
|
||||
"title": "ComfyUI_LLM_Embeder",
|
||||
"reference": "https://github.com/RCAKangle/ComfyUI_LLM_Embeder",
|
||||
"files": [
|
||||
"https://github.com/RCAKangle/ComfyUI_LLM_Embeder"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Local LLM chat nodes for ComfyUI, with a clean handoff path to downstream prompt optimization."
|
||||
},
|
||||
{
|
||||
"author": "esp-dev",
|
||||
"title": "comfyui-loadheicimage",
|
||||
"reference": "https://github.com/esp-dev/comfyui-loadheicimage",
|
||||
"files": [
|
||||
"https://github.com/esp-dev/comfyui-loadheicimage"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI custom node that loads images (including HEIC/HEIF) and provides browser-friendly previews."
|
||||
},
|
||||
{
|
||||
"author": "olduvai-jp",
|
||||
"title": "ComfyUI-S3-IO",
|
||||
"reference": "https://github.com/olduvai-jp/ComfyUI-S3-IO",
|
||||
"files": [
|
||||
"https://github.com/olduvai-jp/ComfyUI-S3-IO"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "S3-backed input/output nodes for ComfyUI to browse, load images/videos from S3 buckets and push outputs back to S3 automatically."
|
||||
},
|
||||
{
|
||||
"author": "theluminhub",
|
||||
"title": "ComfyUI-Lumin-Upload",
|
||||
"reference": "https://github.com/theluminhub/ComfyUI-Lumin-Upload",
|
||||
"files": [
|
||||
"https://github.com/theluminhub/ComfyUI-Lumin-Upload"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Upload your ComfyUI generated images and workflow metadata to Lumin."
|
||||
},
|
||||
|
||||
{
|
||||
"author": "SorenWeile",
|
||||
"title": "ComfyUI_MetaSaver",
|
||||
"reference": "https://github.com/SorenWeile/ComfyUI_MetaSaver",
|
||||
"files": [
|
||||
"https://github.com/SorenWeile/ComfyUI_MetaSaver"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A powerful ComfyUI custom node for saving images with flexible custom metadata fields embedded in PNG files."
|
||||
},
|
||||
{
|
||||
"author": "TTPlanetPig",
|
||||
"title": "Comfyui_DreamID-V_wrapper",
|
||||
"reference": "https://github.com/TTPlanetPig/Comfyui_DreamID-V_wrapper",
|
||||
"files": [
|
||||
"https://github.com/TTPlanetPig/Comfyui_DreamID-V_wrapper"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A simple and efficient ComfyUI integration for DreamID-V, a model for identity-preserving video generation that animates reference images using motion from pose videos."
|
||||
},
|
||||
{
|
||||
"author": "danieljanata",
|
||||
"title": "ComfyUI-Prompting-System",
|
||||
"reference": "https://github.com/danieljanata/ComfyUI-Prompting-System",
|
||||
"files": [
|
||||
"https://github.com/danieljanata/ComfyUI-Prompting-System"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Comprehensive prompt management system for ComfyUI with database storage, thumbnail management, advanced search, and cross-platform support."
|
||||
},
|
||||
{
|
||||
"author": "PauldeLavallaz",
|
||||
"title": "[WIP] comfyui_morpheus_model_management",
|
||||
"reference": "https://github.com/PauldeLavallaz/comfyui_morpheus_model_management",
|
||||
"files": [
|
||||
"https://github.com/PauldeLavallaz/comfyui_morpheus_model_management"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Nodo personalizzato per ComfyUI che consente di sfogliare una libreria locale di immagini di talent con interfaccia gallery, filtri avanzati e output multipli. (Description by CC)\nNOTE: The files in the repo are not organized."
|
||||
},
|
||||
|
||||
{
|
||||
"author": "sinanzoo2nd",
|
||||
"title": "ComfyUI Seed Wildcard Pack",
|
||||
@ -31,6 +266,56 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "Provide a simple interface to simplify prompt writing."
|
||||
},
|
||||
{
|
||||
"author": "Suzu008",
|
||||
"title": "ComfyUI-CryptIO",
|
||||
"reference": "https://github.com/Suzu008/ComfyUI-CryptIO",
|
||||
"files": [
|
||||
"https://github.com/Suzu008/ComfyUI-CryptIO"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A collection of custom nodes for ComfyUI"
|
||||
},
|
||||
{
|
||||
"author": "IRCSS",
|
||||
"title": "comfyUI-blender-wrapper",
|
||||
"reference": "https://github.com/IRCSS/comfyUI-blender-wrapper",
|
||||
"files": [
|
||||
"https://github.com/IRCSS/comfyUI-blender-wrapper"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI Blender Wrapper lets you call Blender in headless mode from ComfyUI (or any Python environment), run reusable pipeline stages stored inside files, and pass configs in/out via JSON. It's meant for tech-art / asset-pipeline tasks like cleanup, decimation, unwrap, baking, rigging, etc."
|
||||
},
|
||||
{
|
||||
"author": "calibancode",
|
||||
"title": "ComfyUI-bevvy",
|
||||
"reference": "https://github.com/calibancode/ComfyUI-bevvy",
|
||||
"files": [
|
||||
"https://github.com/calibancode/ComfyUI-bevvy"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI custom node that saves images as WebP."
|
||||
},
|
||||
{
|
||||
"author": "GraftingRayman",
|
||||
"title": "ComfyUI-Games",
|
||||
"reference": "https://github.com/GraftingRayman/ComfyUI-Games",
|
||||
"files": [
|
||||
"https://github.com/GraftingRayman/ComfyUI-Games"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI node providing Tetris game functionality. (Description by CC)"
|
||||
},
|
||||
{
|
||||
"author": "aicuai",
|
||||
"title": "comfyui-save-image-watermark",
|
||||
"reference": "https://github.com/aicuai/comfyui-save-image-watermark",
|
||||
"files": [
|
||||
"https://github.com/aicuai/comfyui-save-image-watermark"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Save images with visible watermarks (logo/text), invisible watermarks (LSB steganography), and metadata embedding. Supports PNG/JPEG/WebP with browser download."
|
||||
},
|
||||
{
|
||||
"author": "migero",
|
||||
"title": "ComfyUI-Equirectangular-Strip",
|
||||
@ -428,334 +713,6 @@
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Simple node to patch ComfyUI generation with the SDXL Flux2VAE arch support."
|
||||
},
|
||||
{
|
||||
"author": "KrakenUnbound",
|
||||
"title": "Kraken Tools",
|
||||
"id": "kraken-tools",
|
||||
"reference": "https://github.com/krakenunbound/comfyui-kraken-tools",
|
||||
"files": [
|
||||
"https://github.com/krakenunbound/comfyui-kraken-tools"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "15 productivity nodes: Kraken Unbound Prompt (vision-enabled prompt builder with Qwen2-VL), WAN Prompt Splitter (cinematic styling), Ollama Prompt Chat (LLM enhancement), LoRA Loader with CivitAI trigger fetching, Dual CLIP Loader (Flux/SD3/SDXL), smart KSampler (AMP handling for WAN/Flow/FP8), Empty Latent with aspect presets, Upscale & Tile Calculator for Ultimate SD Upscale, Resolution Helper, Image Processor, WAN Helper, and more."
|
||||
},
|
||||
{
|
||||
"author": "18yz153",
|
||||
"title": "ComfyUI-Persona-Director",
|
||||
"reference": "https://github.com/c/ComfyUI-Persona-Director",
|
||||
"files": [
|
||||
"https://github.com/18yz153/ComfyUI-Persona-Director"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A visual state machine for consistent character generation. It intelligently maintains character identity, outfits, and locations across multiple generations using LLM-driven state management."
|
||||
},
|
||||
{
|
||||
"author": "bulldog68",
|
||||
"title": "ComfyUI_FMJ_SaveImageVersions",
|
||||
"description": "Image saving with complete metadata (prompts, seed, software versions) + smart loading.",
|
||||
"reference": "https://github.com/bulldog68/ComfyUI_FMJ_SaveImageVersions",
|
||||
"files": [
|
||||
"https://github.com/bulldog68/ComfyUI_FMJ_SaveImageVersions"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"tags": ["save image", "metadonne"],
|
||||
"license": "GNU V3"
|
||||
},
|
||||
{
|
||||
"author": "GonDesign",
|
||||
"title": "ComfyUI-HaoranWanxImageEdit",
|
||||
"reference": "https://github.com/GonDesign/ComfyUI-HaoranWanxImageEdit",
|
||||
"files": [
|
||||
"https://github.com/GonDesign/ComfyUI-HaoranWanxImageEdit"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "API plugin for Alibaba Cloud Wanx 2.1 Image Editing model. Supports 10 functions including stylization, inpainting, and outpainting."
|
||||
},
|
||||
{
|
||||
"author": "BWDrum",
|
||||
"title": "ComfyUI Random Wildcard Loader",
|
||||
"id": "random-wildcard-loader",
|
||||
"reference": "https://github.com/BWDrum/ComfyUI-RandomWildcardLoader",
|
||||
"files": [
|
||||
"https://github.com/BWDrum/ComfyUI-RandomWildcardLoader"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A custom node for randomized prompt generation with __wildcard__ expansion, subfolder filtering, prefix/suffix support, and seed-based reproducibility."
|
||||
},
|
||||
{
|
||||
"author": "solidlime",
|
||||
"title": "Random Image Picker",
|
||||
"reference": "https://github.com/solidlime/Comfyui-Random_Image_Picker",
|
||||
"files": [
|
||||
"https://github.com/solidlime/Comfyui-Random_Image_Picker"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI custom node for flexible image loading with file picker and random folder selection. Features instant preview, auto mode switching, and browser-based file selection.",
|
||||
"nodename_pattern": "RandomImagePicker"
|
||||
},
|
||||
{
|
||||
"author": "mengqin",
|
||||
"title": "Twinflow Node for ComfyUI",
|
||||
"reference": "https://github.com/mengqin/ComfyUI-TwinFlow",
|
||||
"files": [
|
||||
"https://github.com/mengqin/ComfyUI-TwinFlow"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "This is a set of sampling nodes specifically designed for fine-tuning Twinflow models."
|
||||
},
|
||||
{
|
||||
"author": "shmbatom",
|
||||
"title": "Comfyui-ImageAB-Compare",
|
||||
"id": "Comfyui-ImageAB-Compare",
|
||||
"reference": "https://github.com/shmbatom/Comfyui-ImageAB-Compare",
|
||||
"files": [
|
||||
"https://github.com/shmbatom/Comfyui-ImageAB-Compare"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "image split comparison horizontally/vertically, real-time mouse interaction to adjust split ratios, bidirectional linkage between slider and mouse, and the ability to export comparison images with precise split lines."
|
||||
},
|
||||
{
|
||||
"author": "DanrisiUA",
|
||||
"title": "ComfyUI-ZImage-LoRA-Merger",
|
||||
"reference": "https://github.com/DanrisiUA/ComfyUI-ZImage-LoRA-Merger",
|
||||
"files": [
|
||||
"https://github.com/DanrisiUA/ComfyUI-ZImage-LoRA-Merger"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom nodes for combining multiple LoRAs without overexposure on distilled models like Z-Image Turbo"
|
||||
},
|
||||
{
|
||||
"author": "pixixai",
|
||||
"title": "ComfyUI-AlignLayout",
|
||||
"reference": "https://github.com/pixixai/ComfyUI-AlignLayout",
|
||||
"files": [
|
||||
"https://github.com/pixixai/ComfyUI-AlignLayout"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Productivity enhancement extension for ComfyUI featuring radial menus and mouse flick gestures for efficient node alignment, distribution, and resizing. (Description by CC)"
|
||||
},
|
||||
{
|
||||
"author": "MechaBabyAi",
|
||||
"title": "ComfyUI-MechaBabyNodeSearch",
|
||||
"reference": "https://github.com/MechaBabyAi/ComfyUI-MechaBabyNodeSearch",
|
||||
"files": [
|
||||
"https://github.com/MechaBabyAi/ComfyUI-MechaBabyNodeSearch"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Enhance ComfyUI workflow by providing powerful node search, attribute search, and port navigation features with Ctrl+F shortcut support."
|
||||
},
|
||||
{
|
||||
"author": "yangrui511",
|
||||
"title": "ComfyUI-Text-Preserve",
|
||||
"reference": "https://github.com/yangrui511/ComfyUI-Text-Preserve",
|
||||
"files": [
|
||||
"https://github.com/yangrui511/ComfyUI-Text-Preserve"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom node providing text preservation preprocessing for ComfyUI using OCR to identify text regions and apply blur/noise fusion to non-text areas. (Description by CC)"
|
||||
},
|
||||
{
|
||||
"author": "Atsushi888",
|
||||
"title": "easy_prompt_selector_for_comfyui",
|
||||
"reference": "https://github.com/Atsushi888/easy_prompt_selector_for_comfyui",
|
||||
"files": [
|
||||
"https://github.com/Atsushi888/easy_prompt_selector_for_comfyui"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A simple custom node for ComfyUI that loads and provides an all-in-one dropdown selector to build a prompt string."
|
||||
},
|
||||
{
|
||||
"author": "princepainter",
|
||||
"title": "ComfyUI-PainterLTXV2",
|
||||
"reference": "https://github.com/princepainter/ComfyUI-PainterLTXV2",
|
||||
"files": [
|
||||
"https://github.com/princepainter/ComfyUI-PainterLTXV2"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI custom nodes providing LTXV audio-video separation sampling and latent preparation capabilities for professional video generation workflows."
|
||||
},
|
||||
|
||||
{
|
||||
"author": "logicalor",
|
||||
"title": "comfyui_path_sanitizer",
|
||||
"reference": "https://github.com/logicalor/comfyui_path_sanitizer",
|
||||
"files": [
|
||||
"https://github.com/logicalor/comfyui_path_sanitizer"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A ComfyUI custom node that sanitizes strings for use as filesystem paths"
|
||||
},
|
||||
{
|
||||
"author": "rzgarespo",
|
||||
"title": "ComfyUI-diffusiondb",
|
||||
"reference": "https://github.com/rzgarespo/ComfyUI-diffusiondb",
|
||||
"files": [
|
||||
"https://github.com/rzgarespo/ComfyUI-diffusiondb"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "This code gives you the quick access to 14 million text-to-image prompts from the DiffusionDB dataset."
|
||||
},
|
||||
{
|
||||
"author": "bryanmcguire",
|
||||
"title": "comfyui-flux2fun-controlnet",
|
||||
"reference": "https://github.com/bryanmcguire/comfyui-flux2fun-controlnet",
|
||||
"files": [
|
||||
"https://github.com/bryanmcguire/comfyui-flux2fun-controlnet"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI implementation of FLUX.2-dev-Fun-Controlnet-Union from Alibaba's VideoX-Fun"
|
||||
},
|
||||
{
|
||||
"author": "CypherNaught-0x",
|
||||
"title": "ComfyUI_resolution_presets",
|
||||
"reference": "https://github.com/CypherNaught-0x/ComfyUI_resolution_presets",
|
||||
"files": [
|
||||
"https://github.com/CypherNaught-0x/ComfyUI_resolution_presets"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A ComfyUI extension providing optimized resolution presets for multiple AI image generation models with support for various aspect ratios and two node variants."
|
||||
},
|
||||
{
|
||||
"author": "vjumpkung",
|
||||
"title": "ComfyUI-Musubi-Tuner-LoRA-Loader",
|
||||
"reference": "https://github.com/vjumpkung/ComfyUI-Musubi-Tuner-LoRA-Loader",
|
||||
"files": [
|
||||
"https://github.com/vjumpkung/ComfyUI-Musubi-Tuner-LoRA-Loader"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A ComfyUI custom node that enables direct loading of musubi-tuner based LoRAs (Z-Image Turbo, Hunyuan Video 1.5) with automatic in-memory conversion and caching."
|
||||
},
|
||||
{
|
||||
"author": "SnJake",
|
||||
"title": "SnJake_Baikal_Swin_Anime",
|
||||
"reference": "https://github.com/SnJake/SnJake_Baikal_Swin_Anime",
|
||||
"files": [
|
||||
"https://github.com/SnJake/SnJake_Baikal_Swin_Anime"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "SnJake Baikal-Swin-Anime x2 is a custom ComfyUI node for upscaling anime/illustration images with a dedicated restoration model."
|
||||
},
|
||||
{
|
||||
"author": "kishida",
|
||||
"title": "comfyui-text-renderer",
|
||||
"reference": "https://github.com/kishida/comfyui-text-renderer",
|
||||
"files": [
|
||||
"https://github.com/kishida/comfyui-text-renderer"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Text render node for ComfyUI"
|
||||
},
|
||||
{
|
||||
"author": "aliabougazia",
|
||||
"title": "comfyui_pt_security_scanner",
|
||||
"reference": "https://github.com/aliabougazia/comfyui_pt_security_scanner",
|
||||
"files": [
|
||||
"https://github.com/aliabougazia/comfyui_pt_security_scanner"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A ComfyUI custom node that scans PyTorch model files for potential security vulnerabilities without executing them."
|
||||
},
|
||||
{
|
||||
"author": "PBandDev",
|
||||
"title": "comfyui-node-organizer",
|
||||
"reference": "https://github.com/PBandDev/comfyui-node-organizer",
|
||||
"files": [
|
||||
"https://github.com/PBandDev/comfyui-node-organizer"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI extension to organize nodes"
|
||||
},
|
||||
|
||||
{
|
||||
"author": "SanDiegoDude",
|
||||
"title": "ComfyUI-Soprano-TTS",
|
||||
"reference": "https://github.com/SanDiegoDude/ComfyUI-Soprano-TTS",
|
||||
"files": [
|
||||
"https://github.com/SanDiegoDude/ComfyUI-Soprano-TTS"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Ultra-lightweight, high-fidelity text-to-speech for ComfyUI using Soprano TTS."
|
||||
},
|
||||
{
|
||||
"author": "PixWizardry",
|
||||
"title": "ComfyUI_PixQwenImageEditEnhanced",
|
||||
"reference": "https://github.com/PixWizardry/ComfyUI_PixQwenImageEditEnhanced",
|
||||
"files": [
|
||||
"https://github.com/PixWizardry/ComfyUI_PixQwenImageEditEnhanced"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "An enhanced Vision-Language Model (VLM) conditioning node for ComfyUI designed for the Qwen-Image series, supporting up to 5 reference images with customizable system prompts and token tracking."
|
||||
},
|
||||
{
|
||||
"author": "RyukoMatoiFan",
|
||||
"title": "ComfyUI-STARFlow",
|
||||
"reference": "https://github.com/RyukoMatoiFan/ComfyUI-STARFlow",
|
||||
"files": [
|
||||
"https://github.com/RyukoMatoiFan/ComfyUI-STARFlow"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom nodes for STARFlow text-to-image generation in ComfyUI, including checkpoint loader, text encoder, sampler, and VAE decoder."
|
||||
},
|
||||
{
|
||||
"author": "danielwolber-wood",
|
||||
"title": "ComfyUI-FString",
|
||||
"reference": "https://github.com/danielwolber-wood/ComfyUI-FString",
|
||||
"files": [
|
||||
"https://github.com/danielwolber-wood/ComfyUI-FString"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A custom node for ComfyUI that allows you to format strings using Python's string formatting syntax."
|
||||
},
|
||||
{
|
||||
"author": "danielwolber-wood",
|
||||
"title": "ComfyUI-Inspector",
|
||||
"reference": "https://github.com/danielwolber-wood/ComfyUI-Inspector",
|
||||
"files": [
|
||||
"https://github.com/danielwolber-wood/ComfyUI-Inspector"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A custom node for ComfyUI that allows you to inspect any input data with detailed metadata and visual preview."
|
||||
},
|
||||
{
|
||||
"author": "EricRorich",
|
||||
"title": "ComfyUI-face-shaper",
|
||||
"reference": "https://github.com/EricRorich/ComfyUI-face-shaper",
|
||||
"files": [
|
||||
"https://github.com/EricRorich/ComfyUI-face-shaper"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A custom ComfyUI node that draws parametric facial masks with black lines on white or transparent backgrounds. (Description by CC)"
|
||||
},
|
||||
{
|
||||
"author": "danielwolber-wood",
|
||||
"title": "ComfyUI-QuickResolutionSelector",
|
||||
"reference": "https://github.com/danielwolber-wood/ComfyUI-QuickResolutionSelector",
|
||||
"files": [
|
||||
"https://github.com/danielwolber-wood/ComfyUI-QuickResolutionSelector"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A simple custom node for ComfyUI that allows you to quickly select resolution presets from a dropdown menu."
|
||||
},
|
||||
{
|
||||
"author": "fmartinellidev",
|
||||
"title": "ComfyUI-Prompt_util_pack",
|
||||
"reference": "https://github.com/fmartinellidev/ComfyUI-Prompt_util_pack",
|
||||
"files": [
|
||||
"https://github.com/fmartinellidev/ComfyUI-Prompt_util_pack"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A modular toolkit for advanced prompt engineering in ComfyUI designed for dataset creation, LoRA training, and controlled variation."
|
||||
},
|
||||
{
|
||||
"author": "Niutonian",
|
||||
"title": "comfyui_Niutonian_GLM_4_6V",
|
||||
"reference": "https://github.com/Niutonian/comfyui_Niutonian_GLM_4_6V",
|
||||
"files": [
|
||||
"https://github.com/Niutonian/comfyui_Niutonian_GLM_4_6V"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "This is the transformer-based implementation of Niutonian GLM-4.6V nodes for ComfyUI with memory optimizations."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
],
|
||||
"https://github.com/0nikod/ComfyUI-Simple-Prompt": [
|
||||
[
|
||||
"vue-basic"
|
||||
"SimplePrompt"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-Simple-Prompt"
|
||||
@ -507,6 +507,14 @@
|
||||
"title_aux": "Comfyui-Gelbooru"
|
||||
}
|
||||
],
|
||||
"https://github.com/1x1r/comfyui-upscale-by-model": [
|
||||
[
|
||||
"UpscaleImageByUsingModel"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-upscale-by-model"
|
||||
}
|
||||
],
|
||||
"https://github.com/1zhangyy1/comfyui-vidu-nodes": [
|
||||
[
|
||||
"Character2Video",
|
||||
@ -587,8 +595,8 @@
|
||||
],
|
||||
"https://github.com/3R3BOS/ComfyUI-3R3BOS-Pack": [
|
||||
[
|
||||
"Image Comparer (3R3BOS)",
|
||||
"Visual Gatekeeper (3R3BOS)"
|
||||
"Batch Selector (3R3BOS)",
|
||||
"Image Comparer (3R3BOS)"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-3R3BOS-Pack"
|
||||
@ -2730,7 +2738,8 @@
|
||||
],
|
||||
"https://github.com/Anzhc/SDXL-Flux2VAE-ComfyUI-Node": [
|
||||
[
|
||||
"EmptySDXLFlux2LatentImage"
|
||||
"EmptySDXLFlux2LatentImage",
|
||||
"TargetTimeConditioning"
|
||||
],
|
||||
{
|
||||
"title_aux": "SDXL-Flux2VAE-ComfyUI-Node"
|
||||
@ -5963,6 +5972,17 @@
|
||||
"title_aux": "RangeToString"
|
||||
}
|
||||
],
|
||||
"https://github.com/DemonAlone/SimpeStringGenerator_ComfyUI": [
|
||||
[
|
||||
"DiffusionModelGeneratorNode",
|
||||
"ModelGeneratorNode",
|
||||
"SamplerGeneratorNode",
|
||||
"SchedulerGeneratorNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "SimpeStringGenerator_ComfyUI"
|
||||
}
|
||||
],
|
||||
"https://github.com/DemonNCoding/PromptGenerator12Columns": [
|
||||
[
|
||||
"PromptGenerator12Columns_Empty",
|
||||
@ -8718,6 +8738,14 @@
|
||||
"title_aux": "ComfyUI Visual Dimension Selector"
|
||||
}
|
||||
],
|
||||
"https://github.com/GraftingRayman/ComfyUI-Games": [
|
||||
[
|
||||
"TetrisNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-Games"
|
||||
}
|
||||
],
|
||||
"https://github.com/GraftingRayman/ComfyUI-PuLID-Flux-GR": [
|
||||
[
|
||||
"GRApplyPulidFlux",
|
||||
@ -8774,7 +8802,7 @@
|
||||
"GR Text Overlay",
|
||||
"GR Tile and Border Image",
|
||||
"GR Tile and Border Image Random Flip",
|
||||
"GRBatchLoader",
|
||||
"GRAudioSelector",
|
||||
"GRImageSelector",
|
||||
"GRLoraLoader",
|
||||
"GRMenuHook",
|
||||
@ -10021,6 +10049,49 @@
|
||||
"title_aux": "Notification Bridge"
|
||||
}
|
||||
],
|
||||
"https://github.com/IRCSS/comfyUI-blender-wrapper": [
|
||||
[
|
||||
"BlenderGenericNode",
|
||||
"CV2InpaintTexture",
|
||||
"DownloadAndLoadHy3DDelightModel",
|
||||
"DownloadAndLoadHy3DPaintModel",
|
||||
"Hy3DApplyTexture",
|
||||
"Hy3DBPT",
|
||||
"Hy3DBakeFromMultiview",
|
||||
"Hy3DCameraConfig",
|
||||
"Hy3DDelightImage",
|
||||
"Hy3DDiffusersSchedulerConfig",
|
||||
"Hy3DExportMesh",
|
||||
"Hy3DFastSimplifyMesh",
|
||||
"Hy3DGenerateMesh",
|
||||
"Hy3DGenerateMeshMultiView",
|
||||
"Hy3DGetMeshPBRTextures",
|
||||
"Hy3DIMRemesh",
|
||||
"Hy3DLoadMesh",
|
||||
"Hy3DMeshInfo",
|
||||
"Hy3DMeshUVWrap",
|
||||
"Hy3DMeshVerticeInpaintTexture",
|
||||
"Hy3DModelLoader",
|
||||
"Hy3DNvdiffrastRenderer",
|
||||
"Hy3DPostprocessMesh",
|
||||
"Hy3DRenderMultiView",
|
||||
"Hy3DRenderMultiViewDepth",
|
||||
"Hy3DRenderSingleView",
|
||||
"Hy3DSampleMultiView",
|
||||
"Hy3DSetMeshPBRAttributes",
|
||||
"Hy3DSetMeshPBRTextures",
|
||||
"Hy3DTorchCompileSettings",
|
||||
"Hy3DUploadMesh",
|
||||
"Hy3DVAEDecode",
|
||||
"Hy3DVAELoader",
|
||||
"Hy3D_2_1SimpleMeshGen",
|
||||
"MESHToTrimesh",
|
||||
"TrimeshToMESH"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyUI-blender-wrapper"
|
||||
}
|
||||
],
|
||||
"https://github.com/ITurchenko/ComfyUI-SizeFromArray": [
|
||||
[
|
||||
"SizeFromArray"
|
||||
@ -13032,6 +13103,20 @@
|
||||
"title_aux": "comfyui-vram-overlay"
|
||||
}
|
||||
],
|
||||
"https://github.com/MajoorWaldi/ComfyUI-Majoor-ImageOps": [
|
||||
[
|
||||
"ImageOpsBlur",
|
||||
"ImageOpsClamp",
|
||||
"ImageOpsColorAjust",
|
||||
"ImageOpsInvert",
|
||||
"ImageOpsMerge",
|
||||
"ImageOpsPreview",
|
||||
"ImageOpsTransform"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-Majoor-ImageOps"
|
||||
}
|
||||
],
|
||||
"https://github.com/Makeezi/ComfyUI-promptLAB": [
|
||||
[
|
||||
"PromptLAB"
|
||||
@ -13736,11 +13821,13 @@
|
||||
"Remove Background",
|
||||
"ReplaceAlpha",
|
||||
"Resize Image and Mask by Side",
|
||||
"SEGS Normalize for Video",
|
||||
"Save Folder as ZIP",
|
||||
"Save To Zip",
|
||||
"SaveFolderAsZip",
|
||||
"Spritesheet Builder",
|
||||
"Spritesheet Preview",
|
||||
"Stabilizer Trim",
|
||||
"VideoMaskEditor",
|
||||
"WAN Frame Calculator"
|
||||
],
|
||||
@ -15128,6 +15215,14 @@
|
||||
"title_aux": "Claude Prompt Generator"
|
||||
}
|
||||
],
|
||||
"https://github.com/PauldeLavallaz/comfyui_morpheus_model_management": [
|
||||
[
|
||||
"MorpheusModelManagement"
|
||||
],
|
||||
{
|
||||
"title_aux": "[WIP] comfyui_morpheus_model_management"
|
||||
}
|
||||
],
|
||||
"https://github.com/PenguinTeo/Comfyui-GeminiBanana": [
|
||||
[
|
||||
"Gemini3ImageNode"
|
||||
@ -15863,6 +15958,16 @@
|
||||
"title_aux": "ComfyUI-RED-UNO"
|
||||
}
|
||||
],
|
||||
"https://github.com/QuackPhuc/ComfyUI-FisheyeTransform": [
|
||||
[
|
||||
"FisheyeRedistort",
|
||||
"FisheyeStrengthEstimate",
|
||||
"FisheyeUndistort"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-FisheyeTransform"
|
||||
}
|
||||
],
|
||||
"https://github.com/QuietNoise/comfyui_queue_manager": [
|
||||
[
|
||||
"Workflow Name"
|
||||
@ -15879,6 +15984,16 @@
|
||||
"title_aux": "Universal LLM Node for ComfyUI"
|
||||
}
|
||||
],
|
||||
"https://github.com/RCAKangle/ComfyUI_LLM_Embeder": [
|
||||
[
|
||||
"ChatHistoryViewer",
|
||||
"ChatNode",
|
||||
"LLMConfigNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_LLM_Embeder"
|
||||
}
|
||||
],
|
||||
"https://github.com/RUiNtheExtinct/comfyui-save-file-extended": [
|
||||
[
|
||||
"LoadAudioExtended",
|
||||
@ -17291,6 +17406,19 @@
|
||||
"title_aux": "HF-Flux-ComfyUI"
|
||||
}
|
||||
],
|
||||
"https://github.com/SergPoletaev/ComfyUI-SPoletNodes": [
|
||||
[
|
||||
"EnhancedVideoPreview",
|
||||
"GetImageSizeWithPreview",
|
||||
"Save Images & Preview",
|
||||
"UltimateMemoryCleaner",
|
||||
"Video Concat (FFmpeg)",
|
||||
"VideoBatchCrossfade"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-SPoletNodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/ServiceStack/comfy-asset-downloader": [
|
||||
[
|
||||
"AssetDownloader"
|
||||
@ -18171,6 +18299,15 @@
|
||||
"title_aux": "MBM's Music Visualizer"
|
||||
}
|
||||
],
|
||||
"https://github.com/SorenWeile/ComfyUI_MetaSaver": [
|
||||
[
|
||||
"MetaSaver",
|
||||
"MetaSaverDynamic"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_MetaSaver"
|
||||
}
|
||||
],
|
||||
"https://github.com/SozeInc/ComfyUI-Mobile": [
|
||||
[
|
||||
"Send Notification (Mobile)",
|
||||
@ -18712,6 +18849,7 @@
|
||||
"Basic data handling: TimeExtract",
|
||||
"Basic data handling: TimeFormat",
|
||||
"Basic data handling: TimeNow",
|
||||
"Basic data handling: TimeNowUTC",
|
||||
"Basic data handling: TimeParse",
|
||||
"Basic data handling: TimeSubtractDelta",
|
||||
"Basic data handling: TimeToUnix",
|
||||
@ -19233,6 +19371,21 @@
|
||||
"title_aux": "Comfyroll Studio"
|
||||
}
|
||||
],
|
||||
"https://github.com/Suzu008/ComfyUI-CryptIO": [
|
||||
[
|
||||
"PreviewImageCryptIO",
|
||||
"PreviewVideoCryptIO",
|
||||
"SaveImageCryptIO",
|
||||
"SaveVideoCryptIO",
|
||||
"TextDecrypt",
|
||||
"TextEncrypt",
|
||||
"UploadImageCryptIO",
|
||||
"UploadVideoCryptIO"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-CryptIO"
|
||||
}
|
||||
],
|
||||
"https://github.com/SuzumiyaAkizuki/ComfyUI-LLM_Prompt_XML_Formatter": [
|
||||
[
|
||||
"LLM_Prompt_Formatter",
|
||||
@ -19521,6 +19674,17 @@
|
||||
"title_aux": "tri3d-comfyui-nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/TTPlanetPig/Comfyui_DreamID-V_wrapper": [
|
||||
[
|
||||
"DreamIDV_ConditioningPrep_TTP",
|
||||
"DreamIDV_ModelLoader_Wrapper_TTP",
|
||||
"DreamIDV_PoseExtractor_TTP",
|
||||
"DreamIDV_Sampler_Wrapper_TTP"
|
||||
],
|
||||
{
|
||||
"title_aux": "Comfyui_DreamID-V_wrapper"
|
||||
}
|
||||
],
|
||||
"https://github.com/TTPlanetPig/Comfyui_Hunyuan3D": [
|
||||
[
|
||||
"GifImageViewerNode",
|
||||
@ -20083,6 +20247,8 @@
|
||||
[
|
||||
"CharacterLoraSelect",
|
||||
"ChromaActionSelect",
|
||||
"EasyArrayFilter",
|
||||
"EasyBasicJsonExtractor",
|
||||
"EasyCLIPLoader",
|
||||
"EasyCheckpointLoader",
|
||||
"EasyFileName",
|
||||
@ -20100,6 +20266,8 @@
|
||||
"LoadImagesFromDirectoryPath",
|
||||
"LoadRandomImageFromFolderPath",
|
||||
"QwenActionSelect",
|
||||
"TileAssembly",
|
||||
"TileBreak",
|
||||
"UserSelect",
|
||||
"WanActionSelect"
|
||||
],
|
||||
@ -22485,6 +22653,14 @@
|
||||
"title_aux": "ComfyUI_Detonate"
|
||||
}
|
||||
],
|
||||
"https://github.com/aadityamundhalia/ComfyUI-ollama-aditya": [
|
||||
[
|
||||
"OllamaPromptGenerator"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-ollama-aditya"
|
||||
}
|
||||
],
|
||||
"https://github.com/abdozmantar/ComfyUI-DeepExtract": [
|
||||
[
|
||||
"VocalAndSoundRemoverNode"
|
||||
@ -22948,6 +23124,16 @@
|
||||
"title_aux": "aicu-comfyui-stability-ai-api"
|
||||
}
|
||||
],
|
||||
"https://github.com/aicuai/comfyui-save-image-watermark": [
|
||||
[
|
||||
"ExtractInvisibleWatermark",
|
||||
"Local Save",
|
||||
"LocalSaveImageWithWatermark"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-save-image-watermark"
|
||||
}
|
||||
],
|
||||
"https://github.com/aidec/Comfyui_TextBatch_aidec": [
|
||||
[
|
||||
"DataTempManager",
|
||||
@ -23232,7 +23418,6 @@
|
||||
"GetImagesFromBatchIndexed",
|
||||
"GetLatentRangeFromBatch",
|
||||
"GetLatentSizeAndCount",
|
||||
"Image Comparer (rgthree)",
|
||||
"ImageAddMulti",
|
||||
"ImageAndMaskPreview",
|
||||
"ImageBatchExtendWithOverlap",
|
||||
@ -23257,6 +23442,7 @@
|
||||
"ImagePadKJ",
|
||||
"ImagePass",
|
||||
"ImagePrepForICLora",
|
||||
"ImageResizeByMegapixels",
|
||||
"ImageResizeKJ",
|
||||
"ImageResizeKJv2",
|
||||
"ImageTensorList",
|
||||
@ -23275,6 +23461,7 @@
|
||||
"LoadImagesFromFolderKJ",
|
||||
"LoadVideosFromFolder",
|
||||
"Mask_transform_sum",
|
||||
"MathExpression_UTK",
|
||||
"MergeBatch",
|
||||
"MergeImageChannels",
|
||||
"PadImageBatchInterleaved",
|
||||
@ -23587,6 +23774,8 @@
|
||||
"GeminiConvertRasterToVector",
|
||||
"GeminiFLUXResolutions",
|
||||
"GeminiImageGenerator",
|
||||
"GeminiLoadImagePath",
|
||||
"GeminiLoadImagesFromDir",
|
||||
"GeminiSVGPreview",
|
||||
"GeminiSaveSVG",
|
||||
"GeminiSaveText",
|
||||
@ -23894,10 +24083,15 @@
|
||||
"XJSamplerAdapter",
|
||||
"XJSaveImageWithMetadata",
|
||||
"XJSchedulerAdapter",
|
||||
"XJSegsAutoAdjustHookProvider",
|
||||
"XJSegsColorCorrectHSVHookProvider",
|
||||
"XJSegsColorCorrectRGBHookProvider",
|
||||
"XJSegsColorMatchHookProvider",
|
||||
"XJSegsCount",
|
||||
"XJSegsExtractor",
|
||||
"XJSegsFilter",
|
||||
"XJSegsFilterByLabel",
|
||||
"XJSegsMerge",
|
||||
"XJSegsPick",
|
||||
"XJSegsStitcher",
|
||||
"XJSegsWildcardPrompt",
|
||||
@ -25593,6 +25787,14 @@
|
||||
"title_aux": "ComfyUI-Hunyuan-Image-3"
|
||||
}
|
||||
],
|
||||
"https://github.com/bhhtr12/ComfyUI-ollama-stop": [
|
||||
[
|
||||
"OllamaStopNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-ollama-stop"
|
||||
}
|
||||
],
|
||||
"https://github.com/bhvbhushan/ComfyUI-LoRABlockWeight": [
|
||||
[
|
||||
"HierarchicalLoRAWeightEditor",
|
||||
@ -26861,6 +27063,14 @@
|
||||
"title_aux": "Arc2Face ComfyUI Node Library"
|
||||
}
|
||||
],
|
||||
"https://github.com/calibancode/ComfyUI-bevvy": [
|
||||
[
|
||||
"SaveImageWebP"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-bevvy"
|
||||
}
|
||||
],
|
||||
"https://github.com/camenduru/ComfyUI-TostAI": [
|
||||
[
|
||||
"SendToTostAI"
|
||||
@ -26878,6 +27088,14 @@
|
||||
"title_aux": "Capitan-ConditioningEnhancer"
|
||||
}
|
||||
],
|
||||
"https://github.com/capitan01R/ComfyUI-CapitanZiT-Scheduler": [
|
||||
[
|
||||
"CapitanZiTLinearSigma"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-CapitanZiT-Scheduler"
|
||||
}
|
||||
],
|
||||
"https://github.com/cardenluo/ComfyUI-Apt_Preset": [
|
||||
[
|
||||
"AD_DrawSchedule",
|
||||
@ -26897,6 +27115,8 @@
|
||||
"AD_sch_value",
|
||||
"AD_slice_Condi",
|
||||
"AI_GLM4",
|
||||
"AI_GLM_image",
|
||||
"AI_GLM_text",
|
||||
"AI_Ollama_image",
|
||||
"AI_Ollama_text",
|
||||
"AI_PresetSave",
|
||||
@ -27187,7 +27407,6 @@
|
||||
"sum_lora",
|
||||
"sum_stack_AD",
|
||||
"sum_stack_Kontext",
|
||||
"sum_stack_QwenEdit",
|
||||
"sum_stack_QwenEditPlus",
|
||||
"sum_stack_Wan",
|
||||
"sum_stack_image",
|
||||
@ -29566,6 +29785,13 @@
|
||||
"MaskComposite",
|
||||
"MaskPreview",
|
||||
"MaskToImage",
|
||||
"MeshyAnimateModelNode",
|
||||
"MeshyImageToModelNode",
|
||||
"MeshyMultiImageToModelNode",
|
||||
"MeshyRefineNode",
|
||||
"MeshyRigModelNode",
|
||||
"MeshyTextToModelNode",
|
||||
"MeshyTextureNode",
|
||||
"MinimaxHailuoVideoNode",
|
||||
"MinimaxImageToVideoNode",
|
||||
"MinimaxSubjectToVideoNode",
|
||||
@ -30753,6 +30979,17 @@
|
||||
"title_aux": "ComfyUI-TTS"
|
||||
}
|
||||
],
|
||||
"https://github.com/danieljanata/ComfyUI-Prompting-System": [
|
||||
[
|
||||
"PS_MetadataCleaner",
|
||||
"PS_MetadataReader",
|
||||
"PS_PromptSaver",
|
||||
"PS_SmartText"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-Prompting-System"
|
||||
}
|
||||
],
|
||||
"https://github.com/danielvw/ComfyUI-WanMove-Adapter": [
|
||||
[
|
||||
"CoordsToWanTracks"
|
||||
@ -30924,6 +31161,7 @@
|
||||
"PromptCameraSelector",
|
||||
"PromptConstructor",
|
||||
"PromptLightingSelector",
|
||||
"Test1",
|
||||
"TiledKSampler",
|
||||
"TiledKSamplerWithUpscaler",
|
||||
"TrainingDatasetSaver"
|
||||
@ -32348,6 +32586,14 @@
|
||||
"title_aux": "ComfyUI-enricos-nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/esp-dev/comfyui-loadheicimage": [
|
||||
[
|
||||
"LoadImagePlusHEIC"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-loadheicimage"
|
||||
}
|
||||
],
|
||||
"https://github.com/esp-dev/comfyui-videoframenode": [
|
||||
[
|
||||
"VideoFirstLastFrame"
|
||||
@ -37581,6 +37827,51 @@
|
||||
"title_aux": "HouseKeeper"
|
||||
}
|
||||
],
|
||||
"https://github.com/joe002/comfyui-conduit-optimizer": [
|
||||
[
|
||||
"ConduitApply",
|
||||
"ConduitBatchOptimizer",
|
||||
"ConduitCacheClear",
|
||||
"ConduitCore",
|
||||
"ConduitEmbeddingCache",
|
||||
"ConduitGate",
|
||||
"ConduitLatentCache",
|
||||
"ConduitPath",
|
||||
"ConduitPool",
|
||||
"ConduitPrecisionPatcher",
|
||||
"ConduitSeal",
|
||||
"ConduitSense",
|
||||
"ConduitSpeculativeKSampler"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-conduit-optimizer"
|
||||
}
|
||||
],
|
||||
"https://github.com/joe002/comfyui-deterministic-nodes": [
|
||||
[
|
||||
"CascadeRefiner",
|
||||
"ChecksumValidator",
|
||||
"DeterministicSampler",
|
||||
"ECHOContextNode",
|
||||
"MoERouterNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-deterministic-nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/joe002/comfyui-rtx4090-nodes": [
|
||||
[
|
||||
"BatchImageProcessor",
|
||||
"BatchLatentProcessor",
|
||||
"GPUMonitor",
|
||||
"MemoryManager",
|
||||
"RTX4090Optimizer",
|
||||
"TensorRTAutoConverter"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-rtx4090-nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/joeriben/ai4artsed_comfyui_nodes": [
|
||||
[
|
||||
"ai4artsed_conditioning_fusion",
|
||||
@ -41670,6 +41961,81 @@
|
||||
"title_aux": "ComfyUI-Replace-First-Frame-Last-Frame"
|
||||
}
|
||||
],
|
||||
"https://github.com/loz2754/AUN-ComfyUI-Nodes": [
|
||||
[
|
||||
"AUNAddToPrompt",
|
||||
"AUNAny",
|
||||
"AUNBookmark",
|
||||
"AUNBoolean",
|
||||
"AUNCFG",
|
||||
"AUNCheckpointLoaderWithClipSkip",
|
||||
"AUNEmptyLatent",
|
||||
"AUNExtractModelName",
|
||||
"AUNExtractPowerLoras",
|
||||
"AUNExtractWidgetValue",
|
||||
"AUNGetActiveNodeTitle",
|
||||
"AUNGetConnectedNodeTitles",
|
||||
"AUNGraphScraper",
|
||||
"AUNImageLoadResize",
|
||||
"AUNImageResize",
|
||||
"AUNImageSingleBatch3",
|
||||
"AUNImg2Img",
|
||||
"AUNImgLoader",
|
||||
"AUNInputs",
|
||||
"AUNInputsHybrid",
|
||||
"AUNKSamplerPlusv3",
|
||||
"AUNModelNamePass",
|
||||
"AUNModelShorten",
|
||||
"AUNMultiBypassIndex",
|
||||
"AUNMultiGroupUniversal",
|
||||
"AUNMultiMuteIndex",
|
||||
"AUNMultiNegPrompt",
|
||||
"AUNMultiUniversal",
|
||||
"AUNNameCrop",
|
||||
"AUNNodeStateController",
|
||||
"AUNPathFilename",
|
||||
"AUNPathFilenameVideo",
|
||||
"AUNRandomAnySwitch",
|
||||
"AUNRandomIndexSwitch",
|
||||
"AUNRandomNumber",
|
||||
"AUNRandomTextIndexSwitch",
|
||||
"AUNSaveImage",
|
||||
"AUNSaveVideo",
|
||||
"AUNSetBypassByTitle",
|
||||
"AUNSetBypassStateGroup",
|
||||
"AUNSetCollapseAndBypassStateAdvanced",
|
||||
"AUNSetMuteByTitle",
|
||||
"AUNSetMuteStateGroup",
|
||||
"AUNShowTextWithTitle",
|
||||
"AUNSingleLabelSwitch",
|
||||
"AUNStrip",
|
||||
"AUNSwitchFloat",
|
||||
"AUNTextIndexSwitch",
|
||||
"AUNTextIndexSwitch3",
|
||||
"AUNTitleImagePreview",
|
||||
"AnyType(str)",
|
||||
"AudioInputOptions",
|
||||
"JNodes_AnyToString",
|
||||
"JNodes_ConditioningInOut",
|
||||
"JNodes_FloatLiteral",
|
||||
"JNodes_GetCleanFilename",
|
||||
"JNodes_GetComfyDirectory",
|
||||
"JNodes_GetLeafDirectory",
|
||||
"JNodes_GetOutputDirectory",
|
||||
"JNodes_GetTempDirectory",
|
||||
"JNodes_IntLiteral",
|
||||
"JNodes_ModelInOut",
|
||||
"JNodes_StringLiteral",
|
||||
"JNodes_SubdirectorySelector",
|
||||
"JoinVideosInDirectory",
|
||||
"KSamplerInputs",
|
||||
"MainFolderManualName",
|
||||
"TextSwitch2InputWithTextOutput"
|
||||
],
|
||||
{
|
||||
"title_aux": "AUN ComfyUI Nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/lquesada/ComfyUI-Inpaint-CropAndStitch": [
|
||||
[
|
||||
"InpaintCropImproved",
|
||||
@ -43107,6 +43473,14 @@
|
||||
"title_aux": "comfyui-sora-node"
|
||||
}
|
||||
],
|
||||
"https://github.com/maximilianwicen/ComfyUI-MaxTools": [
|
||||
[
|
||||
"MaxQuickImageSize"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-MaxTools"
|
||||
}
|
||||
],
|
||||
"https://github.com/maxious/comfyui-dap": [
|
||||
[
|
||||
"DAP_ERP_to_Cubemap",
|
||||
@ -45418,6 +45792,57 @@
|
||||
"title_aux": "ComfyUI-HfLoader"
|
||||
}
|
||||
],
|
||||
"https://github.com/olduvai-jp/ComfyUI-S3-IO": [
|
||||
[
|
||||
"LoadImageS3",
|
||||
"LoadVideoUploadS3",
|
||||
"SaveImageS3",
|
||||
"VHS_AudioToVHSAudio",
|
||||
"VHS_BatchManager",
|
||||
"VHS_DuplicateImages",
|
||||
"VHS_DuplicateLatents",
|
||||
"VHS_DuplicateMasks",
|
||||
"VHS_GetImageCount",
|
||||
"VHS_GetLatentCount",
|
||||
"VHS_GetMaskCount",
|
||||
"VHS_LoadAudio",
|
||||
"VHS_LoadAudioUpload",
|
||||
"VHS_LoadImagePath",
|
||||
"VHS_LoadImages",
|
||||
"VHS_LoadImagesPath",
|
||||
"VHS_LoadVideo",
|
||||
"VHS_LoadVideoFFmpeg",
|
||||
"VHS_LoadVideoFFmpegPath",
|
||||
"VHS_LoadVideoPath",
|
||||
"VHS_MergeImages",
|
||||
"VHS_MergeLatents",
|
||||
"VHS_MergeMasks",
|
||||
"VHS_PruneOutputs",
|
||||
"VHS_SelectEveryNthImage",
|
||||
"VHS_SelectEveryNthLatent",
|
||||
"VHS_SelectEveryNthMask",
|
||||
"VHS_SelectFilename",
|
||||
"VHS_SelectImages",
|
||||
"VHS_SelectLatents",
|
||||
"VHS_SelectLatest",
|
||||
"VHS_SelectMasks",
|
||||
"VHS_SplitImages",
|
||||
"VHS_SplitLatents",
|
||||
"VHS_SplitMasks",
|
||||
"VHS_Unbatch",
|
||||
"VHS_VAEDecodeBatched",
|
||||
"VHS_VAEEncodeBatched",
|
||||
"VHS_VHSAudioToAudio",
|
||||
"VHS_VideoCombine",
|
||||
"VHS_VideoInfo",
|
||||
"VHS_VideoInfoLoaded",
|
||||
"VHS_VideoInfoSource",
|
||||
"VideoCombineS3"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-S3-IO"
|
||||
}
|
||||
],
|
||||
"https://github.com/oleksandr612/ComfyUI-Counter": [
|
||||
[
|
||||
"Simple Counter"
|
||||
@ -46611,6 +47036,7 @@
|
||||
"Lora Loader Str",
|
||||
"MaskEmptyFloatNode",
|
||||
"MaskPassOrPlaceholder",
|
||||
"MonoToStereoConverter",
|
||||
"ParametricEQNode",
|
||||
"PonyFaceEnhancementPipelineWithInjection",
|
||||
"PonyUpscaleSamplerWithInjection",
|
||||
@ -49833,6 +50259,7 @@
|
||||
"LoRAExtractKnee",
|
||||
"LoRAExtractQuantile",
|
||||
"LoRAExtractRatio",
|
||||
"LoRAMergeToModel",
|
||||
"LoRAMetaKeys",
|
||||
"LoRAMultiMerge",
|
||||
"LoRAPruneKeys",
|
||||
@ -51922,6 +52349,14 @@
|
||||
"title_aux": "SANA_LOWVRAM"
|
||||
}
|
||||
],
|
||||
"https://github.com/tabisheva/comfyui-segs-profile": [
|
||||
[
|
||||
"SEGSIsProfile"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui-segs-profile"
|
||||
}
|
||||
],
|
||||
"https://github.com/tackcrypto1031/tk_comfyui_img2mask": [
|
||||
[
|
||||
"TK_Image2Mask"
|
||||
@ -51930,6 +52365,14 @@
|
||||
"title_aux": "tk_comfyui_img2mask"
|
||||
}
|
||||
],
|
||||
"https://github.com/tackcrypto1031/tk_comfyui_view_and_light": [
|
||||
[
|
||||
"TK_View_And_Light"
|
||||
],
|
||||
{
|
||||
"title_aux": "tk_comfyui_view_and_light"
|
||||
}
|
||||
],
|
||||
"https://github.com/takemetosiberia/ComfyUI-SAMURAI--SAM2-": [
|
||||
[
|
||||
"SAMURAIBoxInputNode",
|
||||
@ -52191,6 +52634,14 @@
|
||||
"title_aux": "Divergent Nodes"
|
||||
}
|
||||
],
|
||||
"https://github.com/theluminhub/ComfyUI-Lumin-Upload": [
|
||||
[
|
||||
"AssetManagerNode"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-Lumin-Upload"
|
||||
}
|
||||
],
|
||||
"https://github.com/theshubzworld/ComfyUI-FaceCalloutNode": [
|
||||
[
|
||||
"FaceCalloutEffect",
|
||||
@ -53270,8 +53721,7 @@
|
||||
"DisTorchPurgeVRAMV2",
|
||||
"MemoryManager",
|
||||
"ModelPatchMemoryCleaner",
|
||||
"PatchSageAttentionDM",
|
||||
"SafeMemoryManager"
|
||||
"PatchSageAttentionDM"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-DistorchMemoryManager"
|
||||
@ -53296,14 +53746,6 @@
|
||||
"title_aux": "ComfyUI-QwenImageLoraLoader"
|
||||
}
|
||||
],
|
||||
"https://github.com/ussoewwin/image_resize_comfyui": [
|
||||
[
|
||||
"ImageResizeAdvanced"
|
||||
],
|
||||
{
|
||||
"title_aux": "image-resize-comfyui"
|
||||
}
|
||||
],
|
||||
"https://github.com/vadimcro/VKRiez-Edge": [
|
||||
[
|
||||
"VKriezEnhancedEdgePreprocessor",
|
||||
@ -54378,23 +54820,15 @@
|
||||
],
|
||||
"https://github.com/willmiao/ComfyUI-Lora-Manager": [
|
||||
[
|
||||
"BasicScheduler",
|
||||
"CFGGuider",
|
||||
"CLIPTextEncode",
|
||||
"DebugMetadata",
|
||||
"KSamplerSelect",
|
||||
"LoraDemoNode",
|
||||
"LoraManagerLoader",
|
||||
"LoraManagerTextLoader",
|
||||
"LoraPoolNode",
|
||||
"LoraRandomizerNode",
|
||||
"LoraStacker",
|
||||
"PromptLoraManager",
|
||||
"SamplerCustomAdvanced",
|
||||
"SaveImageLM",
|
||||
"TSC_EfficientLoader",
|
||||
"TriggerWordToggle",
|
||||
"VAEDecode",
|
||||
"WanVideoLoraSelectFromText",
|
||||
"WanVideoLoraSelectLM"
|
||||
],
|
||||
|
||||
24
openapi.yaml
24
openapi.yaml
@ -250,6 +250,30 @@ paths:
|
||||
type: object
|
||||
additionalProperties:
|
||||
$ref: '#/components/schemas/NodePackageMetadata'
|
||||
|
||||
/customnode/get_node_types_in_workflows:
|
||||
get:
|
||||
summary: List node types used by all user workflows
|
||||
description: Scan through all workflows in the Comfy user directory, and return a list of all node types used in each one.
|
||||
responses:
|
||||
'200':
|
||||
description: Successful operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
workflow_file_name:
|
||||
type: string
|
||||
node_types:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
|
||||
'500':
|
||||
description: Error occurred
|
||||
|
||||
/customnode/alternatives:
|
||||
get:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user