mirror of
https://git.datalinker.icu/ltdrdata/ComfyUI-Manager
synced 2025-12-08 21:54:26 +08:00
Merge remote-tracking branch 'origin/main' into backport/comfyui-versions-pick-latest
This commit is contained in:
commit
22a5992b11
32
README.md
32
README.md
@ -5,6 +5,7 @@
|
||||

|
||||
|
||||
## NOTICE
|
||||
* V3.38: **Security patch** - Manager data migrated to protected path. See [Migration Guide](docs/en/v3.38-userdata-security-migration.md).
|
||||
* V3.16: Support for `uv` has been added. Set `use_uv` in `config.ini`.
|
||||
* V3.10: `double-click feature` is removed
|
||||
* This feature has been moved to https://github.com/ltdrdata/comfyui-connection-helper
|
||||
@ -140,20 +141,27 @@ This repository provides Colab notebooks that allow you to install and use Comfy
|
||||
|
||||
|
||||
## Paths
|
||||
In `ComfyUI-Manager` V3.0 and later, configuration files and dynamically generated files are located under `<USER_DIRECTORY>/default/ComfyUI-Manager/`.
|
||||
Starting from V3.38, Manager uses a protected system path for enhanced security.
|
||||
|
||||
* <USER_DIRECTORY>
|
||||
* If executed without any options, the path defaults to ComfyUI/user.
|
||||
* It can be set using --user-directory <USER_DIRECTORY>.
|
||||
* <USER_DIRECTORY>
|
||||
* If executed without any options, the path defaults to ComfyUI/user.
|
||||
* It can be set using --user-directory <USER_DIRECTORY>.
|
||||
|
||||
* Basic config files: `<USER_DIRECTORY>/default/ComfyUI-Manager/config.ini`
|
||||
* Configurable channel lists: `<USER_DIRECTORY>/default/ComfyUI-Manager/channels.ini`
|
||||
* Configurable pip overrides: `<USER_DIRECTORY>/default/ComfyUI-Manager/pip_overrides.json`
|
||||
* Configurable pip blacklist: `<USER_DIRECTORY>/default/ComfyUI-Manager/pip_blacklist.list`
|
||||
* Configurable pip auto fix: `<USER_DIRECTORY>/default/ComfyUI-Manager/pip_auto_fix.list`
|
||||
* Saved snapshot files: `<USER_DIRECTORY>/default/ComfyUI-Manager/snapshots`
|
||||
* Startup script files: `<USER_DIRECTORY>/default/ComfyUI-Manager/startup-scripts`
|
||||
* Component files: `<USER_DIRECTORY>/default/ComfyUI-Manager/components`
|
||||
| ComfyUI Version | Manager Path |
|
||||
|-----------------|--------------|
|
||||
| v0.3.76+ (with System User API) | `<USER_DIRECTORY>/__manager/` |
|
||||
| Older versions | `<USER_DIRECTORY>/default/ComfyUI-Manager/` |
|
||||
|
||||
* Basic config files: `config.ini`
|
||||
* Configurable channel lists: `channels.list`
|
||||
* Configurable pip overrides: `pip_overrides.json`
|
||||
* Configurable pip blacklist: `pip_blacklist.list`
|
||||
* Configurable pip auto fix: `pip_auto_fix.list`
|
||||
* Saved snapshot files: `snapshots/`
|
||||
* Startup script files: `startup-scripts/`
|
||||
* Component files: `components/`
|
||||
|
||||
> **Note**: See [Migration Guide](docs/en/v3.38-userdata-security-migration.md) for upgrade details.
|
||||
|
||||
|
||||
## `extra_model_paths.yaml` Configuration
|
||||
|
||||
@ -37293,7 +37293,79 @@
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI custom nodes for Bokeh Diffusion - Defocus Blur Control in Text-to-Image Diffusion Models."
|
||||
},
|
||||
|
||||
{
|
||||
"author": "HAL-XP",
|
||||
"title": "HALXP-Comfy",
|
||||
"reference": "https://github.com/hal-xp/halxp-comfy",
|
||||
"files": [
|
||||
"https://github.com/hal-xp/halxp-comfy"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A UI suite for ComfyUI including Focus mode and layout enhancements."
|
||||
},
|
||||
{
|
||||
"author": "BuddyBytes",
|
||||
"title": "Smart Resolution Toolkit",
|
||||
"reference": "https://github.com/buddy-bytes/ComfyUI-SmartResolutionToolkit",
|
||||
"files": [
|
||||
"https://github.com/buddy-bytes/ComfyUI-SmartResolutionToolkit"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Resolution picker and latent generator for ComfyUI. Select presets like HD, FullHD, 2K, 4K, 8K with aspect ratios (1:1, 9:16, 4:5, 21:9 etc.) via dropdowns. Automatically snaps width/height to latent-safe multiples of 64. Ideal for EmptyLatentImage, AnimateDiff, ControlNet, video formats, and KSampler workflows. Outputs clean INT values or ready-to-use LATENT tensor."
|
||||
},
|
||||
{
|
||||
"author": "Bharanidharan",
|
||||
"title": "iSeeBetter Node for ComfyUI",
|
||||
"reference": "https://github.com/llikethat/ComfyUI-iseebetter",
|
||||
"files": [
|
||||
"https://github.com/llikethat/ComfyUI-iseebetter"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom Node to implement iSeeBetter upscaling method."
|
||||
},
|
||||
{
|
||||
"author": "Pondowner857",
|
||||
"title": "ComfyUI Remote Workflow Executor",
|
||||
"id": "comfy_Pond_Nodes_V2",
|
||||
"reference": "https://github.com/Pondowner857/comfy_Pond_Nodes_V2",
|
||||
"files": [
|
||||
"https://github.com/Pondowner857/comfy_Pond_Nodes_V2"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Remote workflow executor node - Execute workflows on remote ComfyUI servers. Supports image/text/audio/video input and output."
|
||||
},
|
||||
{
|
||||
"author": "luxdelux7",
|
||||
"title": "Forbidden Vision",
|
||||
"reference": "https://github.com/luxdelux7/ComfyUI-Forbidden-Vision",
|
||||
"files": [
|
||||
"https://github.com/luxdelux7/ComfyUI-Forbidden-Vision"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom face detection and segmentation for ComfyUI with automatic face fixing, intelligent color grading, and iterative refinement. Custom-trained models optimized for realistic, anime, and NSFW content.",
|
||||
"nodename_pattern": "ForbiddenVision"
|
||||
},
|
||||
{
|
||||
"author": "ah-kun",
|
||||
"title": "ComfyUI-FailSafe-Translate-Node",
|
||||
"reference": "https://github.com/ah-kun/ComfyUI-FailSafe-Translate-Node",
|
||||
"files": [
|
||||
"https://github.com/ah-kun/ComfyUI-FailSafe-Translate-Node"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Fail-safe Google Translate prompt node for ComfyUI (retry + caching)."
|
||||
},
|
||||
{
|
||||
"author": "Kazama-Suichiku",
|
||||
"title": "ComfyUI-Meshy",
|
||||
"id": "comfyui-meshy",
|
||||
"reference": "https://github.com/Kazama-Suichiku/ComfyUI-Meshy",
|
||||
"files": [
|
||||
"https://github.com/Kazama-Suichiku/ComfyUI-Meshy"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI-Meshy is a 3D generation extension based on Meshy AI API. It provides Text-to-3D and Image-to-3D capabilities within ComfyUI, allowing you to generate 3D models directly from text prompts or images. Supports multiple AI models (Meshy-4, Meshy-5, Meshy-6) with customizable topology, polygon count, and PBR settings."
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
230
docs/en/v3.38-userdata-security-migration.md
Normal file
230
docs/en/v3.38-userdata-security-migration.md
Normal file
@ -0,0 +1,230 @@
|
||||
# ComfyUI-Manager V3.38: Userdata Security Migration Guide
|
||||
|
||||
## Introduction
|
||||
|
||||
ComfyUI-Manager V3.38 introduces a **security patch** that migrates Manager's configuration and data to a protected system path. This change leverages ComfyUI's new System User Protection API (PR #10966) to provide enhanced security isolation.
|
||||
|
||||
This guide explains what happens during the migration and how to handle various situations.
|
||||
|
||||
---
|
||||
|
||||
## What Changed
|
||||
|
||||
### Finding Your Paths
|
||||
|
||||
When ComfyUI starts, it displays the full paths in the terminal:
|
||||
|
||||
```
|
||||
** User directory: /path/to/ComfyUI/user
|
||||
** ComfyUI-Manager config path: /path/to/ComfyUI/user/__manager/config.ini
|
||||
```
|
||||
|
||||
Look for these lines in your startup log to find the exact location on your system. In this guide, paths are shown relative to the `user` directory.
|
||||
|
||||
### Path Migration
|
||||
|
||||
| Data | Legacy Path | New Path |
|
||||
|------|-------------|----------|
|
||||
| Configuration | `user/default/ComfyUI-Manager/` | `user/__manager/` |
|
||||
| Snapshots | `user/default/ComfyUI-Manager/snapshots/` | `user/__manager/snapshots/` |
|
||||
|
||||
### Why This Change
|
||||
|
||||
In older ComfyUI versions, the `default/` directory was **unprotected** and accessible via web APIs. If you ran ComfyUI with `--listen 0.0.0.0` or similar options to allow external connections, this data **may have been tampered with** by malicious actors.
|
||||
|
||||
**Note:** If you only used ComfyUI locally (without `--listen` or with `--listen 127.0.0.1`), your data was not exposed to this vulnerability.
|
||||
|
||||
The new `__manager` path uses ComfyUI's protected system directory, which:
|
||||
- **Cannot be accessed** from outside (protected by ComfyUI)
|
||||
- Isolates system settings from user data
|
||||
- Enables stricter security for remote access
|
||||
|
||||
**This is why only `config.ini` is automatically migrated** - other files (snapshots) may have been compromised and should be manually verified before copying.
|
||||
|
||||
---
|
||||
|
||||
## Automatic Migration
|
||||
|
||||
When you start ComfyUI with the new System User Protection API, Manager automatically handles the migration:
|
||||
|
||||
### Step 1: Configuration Migration
|
||||
|
||||
Only `config.ini` is migrated automatically.
|
||||
|
||||
**Important**: Snapshots are **NOT** automatically migrated. You must copy them manually if needed.
|
||||
|
||||
### Step 2: Security Level Check
|
||||
|
||||
During migration, if your security level is below `normal` (i.e., `weak` or `normal-`), it will be automatically raised to `normal`. This is a safety measure because the security level setting itself may have been tampered with in the old version.
|
||||
|
||||
```
|
||||
======================================================================
|
||||
[ComfyUI-Manager] WARNING: Security level adjusted
|
||||
- Previous: 'weak' → New: 'normal'
|
||||
- Raised to prevent unauthorized remote access.
|
||||
======================================================================
|
||||
```
|
||||
|
||||
If you need a lower security level, you can manually edit the config after migration.
|
||||
|
||||
### Step 3: Legacy Backup
|
||||
|
||||
Your entire legacy directory is moved to a backup location:
|
||||
```
|
||||
user/__manager/.legacy-manager-backup/
|
||||
```
|
||||
|
||||
This backup is preserved until you manually delete it.
|
||||
|
||||
---
|
||||
|
||||
## Persistent Backup Notification
|
||||
|
||||
As long as the backup exists, Manager will remind you on **every startup**:
|
||||
|
||||
```
|
||||
----------------------------------------------------------------------
|
||||
[ComfyUI-Manager] NOTICE: Legacy backup exists
|
||||
- Your old Manager data was backed up to:
|
||||
/path/to/ComfyUI/user/__manager/.legacy-manager-backup
|
||||
- Please verify and remove it when no longer needed.
|
||||
----------------------------------------------------------------------
|
||||
```
|
||||
|
||||
**To stop this notification**: Delete the `.legacy-manager-backup` folder inside `user/__manager/` after confirming you don't need any data from it.
|
||||
|
||||
---
|
||||
|
||||
## Recovering Old Data
|
||||
|
||||
### Snapshots
|
||||
|
||||
If you need your old snapshots, copy the contents of `.legacy-manager-backup/snapshots/` to `user/__manager/snapshots/`.
|
||||
|
||||
---
|
||||
|
||||
## Outdated ComfyUI Warning
|
||||
|
||||
If you're running an older version of ComfyUI without the System User Protection API, Manager will:
|
||||
|
||||
1. **Force security level to `strong`** - All installations are blocked
|
||||
2. **Display warning message**:
|
||||
|
||||
```
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
[ComfyUI-Manager] ERROR: ComfyUI version is outdated!
|
||||
- Most operations are blocked for security.
|
||||
- ComfyUI update is still allowed.
|
||||
- Please update ComfyUI to use Manager normally.
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
```
|
||||
|
||||
**Solution**: Update ComfyUI to v0.3.76 or later.
|
||||
|
||||
---
|
||||
|
||||
## Security Levels
|
||||
|
||||
| Level | What's Allowed |
|
||||
|-------|----------------|
|
||||
| `strong` | ComfyUI update only. All other installations blocked. |
|
||||
| `normal` | Install/update/remove registered custom nodes and models. |
|
||||
| `normal-` | Above + Install via Git URL or pip (localhost only). |
|
||||
| `weak` | All operations allowed, including from remote connections. |
|
||||
|
||||
**Notes:**
|
||||
- `strong` is forced on outdated ComfyUI versions.
|
||||
- `normal` is the default and recommended for most users.
|
||||
- `normal-` is for developers who need to install unregistered nodes locally.
|
||||
- `weak` should only be used in isolated development environments.
|
||||
|
||||
### Changing Security Level
|
||||
|
||||
Edit `user/__manager/config.ini`:
|
||||
```ini
|
||||
[default]
|
||||
security_level = normal
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Messages
|
||||
|
||||
### "comfyui_outdated" (HTTP 403)
|
||||
|
||||
This error appears when:
|
||||
- Your ComfyUI doesn't have the System User Protection API
|
||||
- All installations are blocked until you update ComfyUI
|
||||
|
||||
**Solution**: Update ComfyUI to the latest version.
|
||||
|
||||
### "security_level" (HTTP 403)
|
||||
|
||||
This error appears when:
|
||||
- Your security level blocks the requested operation
|
||||
- For example, `strong` level blocks all installations
|
||||
|
||||
**Solution**: Lower your security level in config.ini if appropriate for your use case.
|
||||
|
||||
---
|
||||
|
||||
## Security Warning: Suspicious Path
|
||||
|
||||
If you see this error on an **older** ComfyUI:
|
||||
|
||||
```
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
[ComfyUI-Manager] ERROR: Suspicious path detected!
|
||||
- '__manager' exists with low security level: 'weak'
|
||||
- Please verify manually:
|
||||
/path/to/ComfyUI/user/__manager/config.ini
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
```
|
||||
|
||||
On older ComfyUI versions, the `__manager` directory is not normally created. If this directory exists, it may have been created externally. For safety, manually verify the contents of this directory before updating ComfyUI.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### All my installations are blocked
|
||||
|
||||
**Check 1**: Is your ComfyUI updated?
|
||||
- Old ComfyUI forces `security_level = strong`
|
||||
- Update ComfyUI to resolve
|
||||
|
||||
**Check 2**: What's your security level?
|
||||
- Check `user/__manager/config.ini`
|
||||
- `security_level = strong` blocks all installations
|
||||
|
||||
### My snapshots are missing
|
||||
|
||||
Snapshots are not automatically migrated. You need to manually copy the `snapshots` folder from inside `.legacy-manager-backup` to the `user/__manager/` directory.
|
||||
|
||||
### I keep seeing the backup notification
|
||||
|
||||
Delete the `.legacy-manager-backup` folder inside `user/__manager/` after confirming you don't need any data from it.
|
||||
|
||||
### Snapshot restore is blocked
|
||||
|
||||
On old ComfyUI (without System User API), snapshot restore is blocked because security is forced to `strong`. Update ComfyUI to enable snapshot restore.
|
||||
|
||||
---
|
||||
|
||||
## File Structure Reference
|
||||
|
||||
```
|
||||
user/
|
||||
└── __manager/
|
||||
├── config.ini # Manager configuration
|
||||
├── channels.list # Custom node channels
|
||||
├── snapshots/ # Environment snapshots
|
||||
└── .legacy-manager-backup/ # Backup of old Manager data (temporary)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Requirements
|
||||
|
||||
- **ComfyUI**: v0.3.76 or later (with System User Protection API)
|
||||
- **ComfyUI-Manager**: V3.38 or later
|
||||
@ -2831,8 +2831,8 @@
|
||||
"GoogleImagenEditNode",
|
||||
"GoogleImagenNode",
|
||||
"NanoBananaNode",
|
||||
"Veo3VideoGenerator",
|
||||
"VeoGeminiVideoGenerator"
|
||||
"VeoGeminiVideoGenerator",
|
||||
"VeoVertexVideoGenerator"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-ExternalAPI-Helpers"
|
||||
@ -6287,6 +6287,7 @@
|
||||
"Multi-LoRA Loader Qwen",
|
||||
"Multi-LoRA Loader Wan-i2v",
|
||||
"Multi-LoRA Loader Wan-t2v",
|
||||
"Multi-LoRA Loader Z-Image",
|
||||
"Multi-LoRA Loader [PLATFORM_NAME]",
|
||||
"Multi-LoRA Loader v02",
|
||||
"MyCustomNode",
|
||||
@ -6306,6 +6307,7 @@
|
||||
],
|
||||
"https://github.com/EricRollei/Comfy_HunyuanImage3": [
|
||||
[
|
||||
"HunyuanImage3ClearDownstream",
|
||||
"HunyuanImage3ForceUnload",
|
||||
"HunyuanImage3FullGPULoader",
|
||||
"HunyuanImage3FullLoader",
|
||||
@ -13828,10 +13830,12 @@
|
||||
"GeomPackFixNormals",
|
||||
"GeomPackFixSelfIntersectionsByPerturbation",
|
||||
"GeomPackFixSelfIntersectionsByRemoval",
|
||||
"GeomPackGetMeshFilename",
|
||||
"GeomPackLoadMesh",
|
||||
"GeomPackLoadMeshBatch",
|
||||
"GeomPackLoadMeshBlend",
|
||||
"GeomPackLoadMeshFBX",
|
||||
"GeomPackMergeVertices",
|
||||
"GeomPackMeshFromSkeleton",
|
||||
"GeomPackMeshInfo",
|
||||
"GeomPackMeshQuality",
|
||||
@ -13848,6 +13852,7 @@
|
||||
"GeomPackRemesh",
|
||||
"GeomPackRemeshSelfIntersections",
|
||||
"GeomPackRemeshWithTexture",
|
||||
"GeomPackRemoveDegenerateFaces",
|
||||
"GeomPackSaveMesh",
|
||||
"GeomPackSaveMeshBatch",
|
||||
"GeomPackTextureToGeometry",
|
||||
@ -14400,6 +14405,8 @@
|
||||
],
|
||||
"https://github.com/Rizzlord/ComfyUI-RizzNodes": [
|
||||
[
|
||||
"BatchImagesToGrid",
|
||||
"LoadMultiviewImages",
|
||||
"RizzAlphaMargin",
|
||||
"RizzBatchImageLoader",
|
||||
"RizzBlur",
|
||||
@ -14414,7 +14421,10 @@
|
||||
"RizzModelBatchLoader",
|
||||
"RizzPasteAndUnscale",
|
||||
"RizzUpscaleImageBatch",
|
||||
"SimplifyMesh"
|
||||
"SaveMultiviewImages",
|
||||
"SimplifyMesh",
|
||||
"SplitImageBatch",
|
||||
"VideoSecondsToLength"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-RizzNodes"
|
||||
@ -18907,6 +18917,7 @@
|
||||
],
|
||||
"https://github.com/WingeD123/ComfyUI_QwenVL_PromptCaption": [
|
||||
[
|
||||
"Ovis25Run",
|
||||
"Qwen25Caption",
|
||||
"Qwen25CaptionBatch",
|
||||
"Qwen3Caption",
|
||||
@ -23320,6 +23331,7 @@
|
||||
],
|
||||
"https://github.com/bradsec/ComfyUI_StringEssentials": [
|
||||
[
|
||||
"StringConditionalAppend",
|
||||
"StringMultiReplace",
|
||||
"StringPreview",
|
||||
"StringStrip",
|
||||
@ -26204,6 +26216,11 @@
|
||||
"KlingImageGenerationNode",
|
||||
"KlingLipSyncAudioToVideoNode",
|
||||
"KlingLipSyncTextToVideoNode",
|
||||
"KlingOmniProEditVideoNode",
|
||||
"KlingOmniProFirstLastFrameNode",
|
||||
"KlingOmniProImageToVideoNode",
|
||||
"KlingOmniProTextToVideoNode",
|
||||
"KlingOmniProVideoToVideoNode",
|
||||
"KlingSingleImageVideoEffectNode",
|
||||
"KlingStartEndFrameNode",
|
||||
"KlingTextToVideoNode",
|
||||
@ -29102,6 +29119,7 @@
|
||||
"HunyuanVideoPromptExpander",
|
||||
"HunyuanVideoTextEncoder",
|
||||
"HunyuanVideoVisionLoader",
|
||||
"LLMOutputParser",
|
||||
"PromptKeyFilter",
|
||||
"QwenDebugController",
|
||||
"QwenEliGenEntityControl",
|
||||
@ -29126,9 +29144,11 @@
|
||||
"QwenVLTextEncoder",
|
||||
"QwenVLTextEncoderAdvanced",
|
||||
"TemplateInfluenceAnalyzer",
|
||||
"ZImageEmptyLatent",
|
||||
"ZImageTextEncoder",
|
||||
"ZImageTextEncoderSimple",
|
||||
"ZImageTurnBuilder"
|
||||
"ZImageTurnBuilder",
|
||||
"ZImageWanVAEDecode"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-QwenImageWanBridge"
|
||||
@ -30634,6 +30654,10 @@
|
||||
"Kling21Pro_fal",
|
||||
"Kling25TurboPro_fal",
|
||||
"KlingMaster_fal",
|
||||
"KlingOmniImageToVideo_fal",
|
||||
"KlingOmniReferenceToVideo_fal",
|
||||
"KlingOmniVideoToVideoEdit_fal",
|
||||
"KlingOmniVideoToVideoReference_fal",
|
||||
"KlingPro10_fal",
|
||||
"KlingPro16_fal",
|
||||
"Kling_fal",
|
||||
@ -31806,10 +31830,9 @@
|
||||
],
|
||||
"https://github.com/hobinrude/ComfyUI_DWposeDeluxe": [
|
||||
[
|
||||
"DWposeKeypointConverter",
|
||||
"DWposeWeightOptions",
|
||||
"FrameNumberNode",
|
||||
"KeypointConverter",
|
||||
"LoadPoseKeypoints",
|
||||
"WeightOptions"
|
||||
],
|
||||
{
|
||||
@ -36486,7 +36509,9 @@
|
||||
[
|
||||
"QwenImageEditScale",
|
||||
"QwenImageEditSimpleScale",
|
||||
"TextEncodeQwenImageEditAdv"
|
||||
"TextEncodeQwenImageEditAdv",
|
||||
"TextEncodeQwenImageEditInfAdv",
|
||||
"TextEncodeQwenImageEditPlusAdv"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui_qwen_image_edit_adv"
|
||||
@ -38480,6 +38505,7 @@
|
||||
"EasyResize",
|
||||
"EasyWan22Prompt",
|
||||
"Easy_Version",
|
||||
"KoolookLoadCameraPosesAbsolute",
|
||||
"easy_ImageBatch"
|
||||
],
|
||||
{
|
||||
@ -42821,6 +42847,12 @@
|
||||
"WaveSpeedAI Flux Kontext Max",
|
||||
"WaveSpeedAI Flux Kontext Pro",
|
||||
"WaveSpeedAI Google Nano Banana Edit",
|
||||
"WaveSpeedAI Google Nano Banana Pro Edit",
|
||||
"WaveSpeedAI Google Nano Banana Pro Edit Multi",
|
||||
"WaveSpeedAI Google Nano Banana Pro Edit Ultra",
|
||||
"WaveSpeedAI Google Nano Banana Pro Text to Image",
|
||||
"WaveSpeedAI Google Nano Banana Pro Text to Image Multi",
|
||||
"WaveSpeedAI Google Nano Banana Pro Text to Image Ultra",
|
||||
"WaveSpeedAI Google Nano Banana Text to Image",
|
||||
"WaveSpeedAI Google VEO 3.1 Fast Image-to-Video",
|
||||
"WaveSpeedAI Google VEO 3.1 Fast Text-to-Video",
|
||||
@ -45260,8 +45292,11 @@
|
||||
],
|
||||
"https://github.com/smthemex/ComfyUI_DiffuEraser": [
|
||||
[
|
||||
"DiffuEraserLoader",
|
||||
"DiffuEraserSampler"
|
||||
"DiffuEraser_Loader",
|
||||
"DiffuEraser_PreData",
|
||||
"DiffuEraser_Sampler",
|
||||
"Propainter_Loader",
|
||||
"Propainter_Sampler"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_DiffuEraser"
|
||||
|
||||
5440
github-stats.json
5440
github-stats.json
File diff suppressed because it is too large
Load Diff
@ -40,10 +40,11 @@ import cnr_utils
|
||||
import manager_util
|
||||
import git_utils
|
||||
import manager_downloader
|
||||
import manager_migration
|
||||
from node_package import InstalledNodePackage
|
||||
|
||||
|
||||
version_code = [3, 37, 2]
|
||||
version_code = [3, 38]
|
||||
version_str = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
|
||||
|
||||
|
||||
@ -214,9 +215,10 @@ def update_user_directory(user_dir):
|
||||
global manager_pip_blacklist_path
|
||||
global manager_components_path
|
||||
|
||||
manager_files_path = os.path.abspath(os.path.join(user_dir, 'default', 'ComfyUI-Manager'))
|
||||
manager_files_path = manager_migration.get_manager_path(user_dir)
|
||||
if not os.path.exists(manager_files_path):
|
||||
os.makedirs(manager_files_path)
|
||||
manager_migration.run_migration_checks(user_dir, manager_files_path)
|
||||
|
||||
manager_snapshot_path = os.path.join(manager_files_path, "snapshots")
|
||||
if not os.path.exists(manager_snapshot_path):
|
||||
@ -1719,7 +1721,7 @@ def read_config():
|
||||
manager_util.use_uv = default_conf['use_uv'].lower() == 'true' if 'use_uv' in default_conf else False
|
||||
manager_util.bypass_ssl = get_bool('bypass_ssl', False)
|
||||
|
||||
return {
|
||||
result = {
|
||||
'http_channel_enabled': get_bool('http_channel_enabled', False),
|
||||
'preview_method': default_conf.get('preview_method', manager_funcs.get_current_preview_method()).lower(),
|
||||
'git_exe': default_conf.get('git_exe', ''),
|
||||
@ -1739,6 +1741,8 @@ def read_config():
|
||||
'security_level': default_conf.get('security_level', 'normal').lower(),
|
||||
'db_mode': default_conf.get('db_mode', 'cache').lower(),
|
||||
}
|
||||
manager_migration.force_security_level_if_needed(result)
|
||||
return result
|
||||
|
||||
except Exception:
|
||||
import importlib.util
|
||||
@ -1746,7 +1750,7 @@ def read_config():
|
||||
manager_util.use_uv = importlib.util.find_spec("uv") is not None and platform.system() != "Windows"
|
||||
manager_util.bypass_ssl = False
|
||||
|
||||
return {
|
||||
result = {
|
||||
'http_channel_enabled': False,
|
||||
'preview_method': manager_funcs.get_current_preview_method(),
|
||||
'git_exe': '',
|
||||
@ -1766,6 +1770,8 @@ def read_config():
|
||||
'security_level': 'normal', # strong | normal | normal- | weak
|
||||
'db_mode': 'cache', # local | cache | remote
|
||||
}
|
||||
manager_migration.force_security_level_if_needed(result)
|
||||
return result
|
||||
|
||||
|
||||
def get_config():
|
||||
@ -3361,7 +3367,7 @@ def get_comfyui_versions(repo=None):
|
||||
try:
|
||||
remote = get_remote_name(repo)
|
||||
repo.remotes[remote].fetch()
|
||||
except Exception:
|
||||
except:
|
||||
logging.error("[ComfyUI-Manager] Failed to fetch ComfyUI")
|
||||
|
||||
def parse_semver(tag_name):
|
||||
|
||||
356
glob/manager_migration.py
Normal file
356
glob/manager_migration.py
Normal file
@ -0,0 +1,356 @@
|
||||
"""
|
||||
ComfyUI-Manager migration module.
|
||||
Handles migration from legacy paths to new __manager path structure.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import configparser
|
||||
|
||||
# Startup notices for notice board
|
||||
startup_notices = [] # List of (message, level) tuples
|
||||
|
||||
|
||||
def add_startup_notice(message, level='warning'):
|
||||
"""Add a notice to be displayed on Manager notice board.
|
||||
|
||||
Args:
|
||||
message: HTML-formatted message string
|
||||
level: 'warning', 'error', 'info'
|
||||
"""
|
||||
global startup_notices
|
||||
startup_notices.append((message, level))
|
||||
|
||||
|
||||
# Cache for API check (computed once per session)
|
||||
_cached_has_system_user_api = None
|
||||
|
||||
|
||||
def has_system_user_api():
|
||||
"""Check if ComfyUI has the System User Protection API (PR #10966).
|
||||
|
||||
Result is cached for performance.
|
||||
"""
|
||||
global _cached_has_system_user_api
|
||||
if _cached_has_system_user_api is None:
|
||||
try:
|
||||
import folder_paths
|
||||
_cached_has_system_user_api = hasattr(folder_paths, 'get_system_user_directory')
|
||||
except Exception:
|
||||
_cached_has_system_user_api = False
|
||||
return _cached_has_system_user_api
|
||||
|
||||
|
||||
def get_manager_path(user_dir):
|
||||
"""Get the appropriate manager files path based on ComfyUI version.
|
||||
|
||||
Returns:
|
||||
str: manager_files_path
|
||||
"""
|
||||
if has_system_user_api():
|
||||
return os.path.abspath(os.path.join(user_dir, '__manager'))
|
||||
else:
|
||||
return os.path.abspath(os.path.join(user_dir, 'default', 'ComfyUI-Manager'))
|
||||
|
||||
|
||||
def run_migration_checks(user_dir, manager_files_path):
|
||||
"""Run all migration and security checks.
|
||||
|
||||
Call this after get_manager_path() to handle:
|
||||
- Legacy config migration (new ComfyUI)
|
||||
- Legacy backup notification (every startup)
|
||||
- Suspicious directory detection (old ComfyUI)
|
||||
- Outdated ComfyUI warning (old ComfyUI)
|
||||
"""
|
||||
if has_system_user_api():
|
||||
migrated = migrate_legacy_config(user_dir, manager_files_path)
|
||||
# Only check for legacy backup if migration didn't just happen
|
||||
# (migration already shows backup location in its message)
|
||||
if not migrated:
|
||||
check_legacy_backup(manager_files_path)
|
||||
else:
|
||||
check_suspicious_manager(user_dir)
|
||||
warn_outdated_comfyui()
|
||||
|
||||
|
||||
def check_legacy_backup(manager_files_path):
|
||||
"""Check for legacy backup and notify user to verify and remove it.
|
||||
|
||||
This runs on every startup to remind users about pending legacy backup.
|
||||
"""
|
||||
backup_dir = os.path.join(manager_files_path, '.legacy-manager-backup')
|
||||
if not os.path.exists(backup_dir):
|
||||
return
|
||||
|
||||
# Terminal output
|
||||
print("\n" + "-"*70)
|
||||
print("[ComfyUI-Manager] NOTICE: Legacy backup exists")
|
||||
print(" - Your old Manager data was backed up to:")
|
||||
print(f" {backup_dir}")
|
||||
print(" - Please verify and remove it when no longer needed.")
|
||||
print("-"*70 + "\n")
|
||||
|
||||
# Notice board output
|
||||
add_startup_notice(
|
||||
"Legacy ComfyUI-Manager data backup exists. Please verify and remove when no longer needed.",
|
||||
level='info'
|
||||
)
|
||||
|
||||
|
||||
def check_suspicious_manager(user_dir):
|
||||
"""Check for suspicious __manager directory on old ComfyUI.
|
||||
|
||||
On old ComfyUI without System User API, if __manager exists with low security,
|
||||
warn the user to verify manually.
|
||||
|
||||
Returns:
|
||||
bool: True if suspicious setup detected
|
||||
"""
|
||||
if has_system_user_api():
|
||||
return False # Not suspicious on new ComfyUI
|
||||
|
||||
suspicious_path = os.path.abspath(os.path.join(user_dir, '__manager'))
|
||||
if not os.path.exists(suspicious_path):
|
||||
return False
|
||||
|
||||
config_path = os.path.join(suspicious_path, 'config.ini')
|
||||
if not os.path.exists(config_path):
|
||||
return False
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config.read(config_path)
|
||||
sec_level = config.get('default', 'security_level', fallback='normal').lower()
|
||||
|
||||
if sec_level in ['weak', 'normal-']:
|
||||
# Terminal output
|
||||
print("\n" + "!"*70)
|
||||
print("[ComfyUI-Manager] ERROR: Suspicious path detected!")
|
||||
print(f" - '__manager' exists with low security level: '{sec_level}'")
|
||||
print(" - Please verify manually:")
|
||||
print(f" {config_path}")
|
||||
print("!"*70 + "\n")
|
||||
|
||||
# Notice board output
|
||||
add_startup_notice(
|
||||
"[Security Alert] Suspicious path detected. See terminal log for details.",
|
||||
level='error'
|
||||
)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def warn_outdated_comfyui():
|
||||
"""Warn user about outdated ComfyUI without System User API."""
|
||||
if has_system_user_api():
|
||||
return
|
||||
|
||||
# Terminal output
|
||||
print("\n" + "!"*70)
|
||||
print("[ComfyUI-Manager] ERROR: ComfyUI version is outdated!")
|
||||
print(" - Most operations are blocked for security.")
|
||||
print(" - ComfyUI update is still allowed.")
|
||||
print(" - Please update ComfyUI to use Manager normally.")
|
||||
print("!"*70 + "\n")
|
||||
|
||||
# Notice board output
|
||||
add_startup_notice(
|
||||
"[Security Alert] ComfyUI outdated. Installations blocked (update allowed).<BR>"
|
||||
"Update ComfyUI for normal operation.",
|
||||
level='error'
|
||||
)
|
||||
|
||||
|
||||
def migrate_legacy_config(user_dir, manager_files_path):
|
||||
"""Migrate ONLY config.ini to new __manager path if needed.
|
||||
|
||||
IMPORTANT: Only config.ini is migrated. Other files (snapshots, cache, etc.)
|
||||
are NOT migrated - users must recreate them.
|
||||
|
||||
Scenarios:
|
||||
1. Legacy exists, New doesn't exist → Migrate config.ini
|
||||
2. Legacy exists, New exists → First update after upgrade
|
||||
- Run ComfyUI dependency installation
|
||||
- Rename legacy to .backup
|
||||
3. Legacy doesn't exist → No migration needed
|
||||
|
||||
Returns:
|
||||
bool: True if migration was performed
|
||||
"""
|
||||
if not has_system_user_api():
|
||||
return False
|
||||
|
||||
legacy_dir = os.path.join(user_dir, 'default', 'ComfyUI-Manager')
|
||||
legacy_config = os.path.join(legacy_dir, 'config.ini')
|
||||
new_config = os.path.join(manager_files_path, 'config.ini')
|
||||
|
||||
if not os.path.exists(legacy_dir):
|
||||
return False # No legacy directory, nothing to migrate
|
||||
|
||||
# IMPORTANT: Check for config.ini existence, not just directory
|
||||
# (because makedirs() creates __manager before this function is called)
|
||||
|
||||
# Case: Both configs exist (first update after ComfyUI upgrade)
|
||||
# This means user ran new ComfyUI at least once, creating __manager/config.ini
|
||||
if os.path.exists(legacy_config) and os.path.exists(new_config):
|
||||
_handle_first_update_migration(user_dir, legacy_dir, manager_files_path)
|
||||
return True
|
||||
|
||||
# Case: Legacy config exists but new config doesn't (normal migration)
|
||||
# This is the first run after ComfyUI upgrade
|
||||
if os.path.exists(legacy_config) and not os.path.exists(new_config):
|
||||
pass # Continue with normal migration below
|
||||
else:
|
||||
return False
|
||||
|
||||
# Terminal output
|
||||
print("\n" + "-"*70)
|
||||
print("[ComfyUI-Manager] NOTICE: Legacy config.ini detected")
|
||||
print(f" - Old: {legacy_config}")
|
||||
print(f" - New: {new_config}")
|
||||
print(" - Migrating config.ini only (other files are NOT migrated).")
|
||||
print(" - Security level below 'normal' will be raised.")
|
||||
print("-"*70 + "\n")
|
||||
|
||||
_migrate_config_with_security_check(legacy_config, new_config)
|
||||
|
||||
# Move legacy directory to backup
|
||||
_move_legacy_to_backup(legacy_dir, manager_files_path)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def _handle_first_update_migration(user_dir, legacy_dir, manager_files_path):
|
||||
"""Handle first ComfyUI update when both legacy and new directories exist.
|
||||
|
||||
This scenario happens when:
|
||||
- User was on old ComfyUI (using default/ComfyUI-Manager)
|
||||
- ComfyUI was updated (now has System User API)
|
||||
- Manager already created __manager on first new run
|
||||
- But legacy directory still exists
|
||||
|
||||
Actions:
|
||||
1. Run ComfyUI dependency installation
|
||||
2. Move legacy to __manager/.legacy-manager-backup
|
||||
"""
|
||||
# Terminal output
|
||||
print("\n" + "-"*70)
|
||||
print("[ComfyUI-Manager] NOTICE: First update after ComfyUI upgrade detected")
|
||||
print(" - Both legacy and new directories exist.")
|
||||
print(" - Running ComfyUI dependency installation...")
|
||||
print("-"*70 + "\n")
|
||||
|
||||
# Run ComfyUI dependency installation
|
||||
# Path: glob/manager_migration.py → glob → comfyui-manager → custom_nodes → ComfyUI
|
||||
try:
|
||||
comfyui_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
|
||||
requirements_path = os.path.join(comfyui_path, 'requirements.txt')
|
||||
if os.path.exists(requirements_path):
|
||||
subprocess.run([sys.executable, '-m', 'pip', 'install', '-r', requirements_path],
|
||||
capture_output=True, check=False)
|
||||
print("[ComfyUI-Manager] ComfyUI dependencies installation completed.")
|
||||
except Exception as e:
|
||||
print(f"[ComfyUI-Manager] WARNING: Failed to install ComfyUI dependencies: {e}")
|
||||
|
||||
# Move legacy to backup inside __manager
|
||||
_move_legacy_to_backup(legacy_dir, manager_files_path)
|
||||
|
||||
|
||||
def _move_legacy_to_backup(legacy_dir, manager_files_path):
|
||||
"""Move legacy directory to backup inside __manager.
|
||||
|
||||
Returns:
|
||||
str: Path to backup directory if successful, None if failed
|
||||
"""
|
||||
import shutil
|
||||
|
||||
backup_dir = os.path.join(manager_files_path, '.legacy-manager-backup')
|
||||
|
||||
try:
|
||||
if os.path.exists(backup_dir):
|
||||
shutil.rmtree(backup_dir) # Remove old backup if exists
|
||||
shutil.move(legacy_dir, backup_dir)
|
||||
|
||||
# Terminal output (full paths shown here only)
|
||||
print("\n" + "-"*70)
|
||||
print("[ComfyUI-Manager] NOTICE: Legacy settings migrated")
|
||||
print(f" - Old location: {legacy_dir}")
|
||||
print(f" - Backed up to: {backup_dir}")
|
||||
print(" - Please verify and remove the backup when no longer needed.")
|
||||
print("-"*70 + "\n")
|
||||
|
||||
# Notice board output (no full paths for security)
|
||||
add_startup_notice(
|
||||
"Legacy ComfyUI-Manager data migrated. See terminal for details.",
|
||||
level='info'
|
||||
)
|
||||
return backup_dir
|
||||
except Exception as e:
|
||||
print(f"[ComfyUI-Manager] WARNING: Failed to backup legacy directory: {e}")
|
||||
add_startup_notice(
|
||||
f"[MIGRATION] Failed to backup legacy directory: {e}",
|
||||
level='warning'
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
def _migrate_config_with_security_check(legacy_path, new_path):
|
||||
"""Migrate legacy config, raising security level only if below default."""
|
||||
config = configparser.ConfigParser()
|
||||
try:
|
||||
config.read(legacy_path)
|
||||
except Exception as e:
|
||||
print(f"[ComfyUI-Manager] WARNING: Failed to parse config.ini: {e}")
|
||||
print(" - Creating fresh config with default settings.")
|
||||
add_startup_notice(
|
||||
"[MIGRATION] Failed to parse legacy config. Using defaults.",
|
||||
level='warning'
|
||||
)
|
||||
return # Skip migration, let Manager create fresh config
|
||||
|
||||
# Security level hierarchy: strong > normal > normal- > weak
|
||||
# Default is 'normal', only raise if below default
|
||||
if 'default' in config:
|
||||
current_level = config['default'].get('security_level', 'normal').lower()
|
||||
below_default_levels = ['weak', 'normal-']
|
||||
|
||||
if current_level in below_default_levels:
|
||||
config['default']['security_level'] = 'normal'
|
||||
|
||||
# Terminal output
|
||||
print("\n" + "="*70)
|
||||
print("[ComfyUI-Manager] WARNING: Security level adjusted")
|
||||
print(f" - Previous: '{current_level}' → New: 'normal'")
|
||||
print(" - Raised to prevent unauthorized remote access.")
|
||||
print("="*70 + "\n")
|
||||
|
||||
# Notice board output
|
||||
add_startup_notice(
|
||||
f"[MIGRATION] Security level raised: '{current_level}' → 'normal'.<BR>"
|
||||
"To prevent unauthorized remote access.",
|
||||
level='warning'
|
||||
)
|
||||
else:
|
||||
print(f" - Security level: '{current_level}' (no change needed)")
|
||||
|
||||
# Ensure directory exists
|
||||
os.makedirs(os.path.dirname(new_path), exist_ok=True)
|
||||
|
||||
with open(new_path, 'w') as f:
|
||||
config.write(f)
|
||||
|
||||
|
||||
def force_security_level_if_needed(config_dict):
|
||||
"""Force security level to 'strong' if on old ComfyUI.
|
||||
|
||||
Args:
|
||||
config_dict: Configuration dictionary to modify in-place
|
||||
|
||||
Returns:
|
||||
bool: True if security level was forced
|
||||
"""
|
||||
if not has_system_user_api():
|
||||
config_dict['security_level'] = 'strong'
|
||||
return True
|
||||
return False
|
||||
@ -22,6 +22,7 @@ import asyncio
|
||||
import queue
|
||||
|
||||
import manager_downloader
|
||||
import manager_migration
|
||||
|
||||
|
||||
logging.info(f"### Loading: ComfyUI-Manager ({core.version_str})")
|
||||
@ -276,6 +277,13 @@ import zipfile
|
||||
import urllib.request
|
||||
|
||||
|
||||
def security_403_response():
|
||||
"""Return appropriate 403 response based on ComfyUI version."""
|
||||
if not manager_migration.has_system_user_api():
|
||||
return web.json_response({"error": "comfyui_outdated"}, status=403)
|
||||
return web.json_response({"error": "security_level"}, status=403)
|
||||
|
||||
|
||||
def get_model_dir(data, show_log=False):
|
||||
if 'download_model_base' in folder_paths.folder_names_and_paths:
|
||||
models_base = folder_paths.folder_names_and_paths['download_model_base'][0][0]
|
||||
@ -732,7 +740,7 @@ async def fetch_updates(request):
|
||||
async def update_all(request):
|
||||
if not is_allowed_security_level('middle'):
|
||||
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
||||
return web.Response(status=403)
|
||||
return security_403_response()
|
||||
|
||||
with task_worker_lock:
|
||||
is_processing = task_worker_thread is not None and task_worker_thread.is_alive()
|
||||
@ -965,7 +973,7 @@ async def get_snapshot_list(request):
|
||||
async def remove_snapshot(request):
|
||||
if not is_allowed_security_level('middle'):
|
||||
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
||||
return web.Response(status=403)
|
||||
return security_403_response()
|
||||
|
||||
try:
|
||||
target = request.rel_url.query["target"]
|
||||
@ -983,7 +991,7 @@ async def remove_snapshot(request):
|
||||
async def restore_snapshot(request):
|
||||
if not is_allowed_security_level('middle'):
|
||||
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
||||
return web.Response(status=403)
|
||||
return security_403_response()
|
||||
|
||||
try:
|
||||
target = request.rel_url.query["target"]
|
||||
@ -1302,7 +1310,7 @@ async def fix_custom_node(request):
|
||||
async def install_custom_node_git_url(request):
|
||||
if not is_allowed_security_level('high'):
|
||||
logging.error(SECURITY_MESSAGE_NORMAL_MINUS)
|
||||
return web.Response(status=403)
|
||||
return security_403_response()
|
||||
|
||||
url = await request.text()
|
||||
res = await core.gitclone_install(url)
|
||||
@ -1322,7 +1330,7 @@ async def install_custom_node_git_url(request):
|
||||
async def install_custom_node_pip(request):
|
||||
if not is_allowed_security_level('high'):
|
||||
logging.error(SECURITY_MESSAGE_NORMAL_MINUS)
|
||||
return web.Response(status=403)
|
||||
return security_403_response()
|
||||
|
||||
packages = await request.text()
|
||||
core.pip_install(packages.split(' '))
|
||||
@ -1594,6 +1602,16 @@ async def get_notice(request):
|
||||
except:
|
||||
pass
|
||||
|
||||
# Prepend startup notices from manager_migration
|
||||
for message, level in reversed(manager_migration.startup_notices):
|
||||
if level == 'error':
|
||||
style = 'color:red; background-color:white; font-weight:bold'
|
||||
elif level == 'warning':
|
||||
style = 'color:orange; background-color:white; font-weight:bold'
|
||||
else:
|
||||
style = 'color:blue; background-color:white'
|
||||
markdown_content = f'<P style="{style}">{message}</P>' + markdown_content
|
||||
|
||||
return web.Response(text=markdown_content, status=200)
|
||||
else:
|
||||
return web.Response(text="Unable to retrieve Notice", status=200)
|
||||
@ -1601,11 +1619,35 @@ async def get_notice(request):
|
||||
return web.Response(text="Unable to retrieve Notice", status=200)
|
||||
|
||||
|
||||
@routes.get("/manager/startup_alerts")
|
||||
async def get_startup_alerts(request):
|
||||
"""Return startup alerts for customAlert display on page load.
|
||||
|
||||
Returns JSON array of alerts that should be shown to user immediately.
|
||||
All startup notices (error, warning, info) are returned.
|
||||
"""
|
||||
alerts = []
|
||||
|
||||
# Return all startup notices for alert display
|
||||
for message, level in manager_migration.startup_notices:
|
||||
# Convert HTML BR to newlines for customAlert
|
||||
text = message.replace('<BR>', '\n').replace('<br>', '\n')
|
||||
# Add [ComfyUI-Manager] prefix for customAlert (notice board shows in Manager UI anyway)
|
||||
text = text.replace('[Security Alert]', '[ComfyUI-Manager] Security Alert:')
|
||||
text = text.replace('[MIGRATION]', '[ComfyUI-Manager] Migration:')
|
||||
alerts.append({
|
||||
'message': text,
|
||||
'level': level
|
||||
})
|
||||
|
||||
return web.json_response(alerts)
|
||||
|
||||
|
||||
@routes.get("/manager/reboot")
|
||||
def restart(self):
|
||||
if not is_allowed_security_level('middle'):
|
||||
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
||||
return web.Response(status=403)
|
||||
return security_403_response()
|
||||
|
||||
try:
|
||||
sys.stdout.close_log()
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { api } from "../../scripts/api.js";
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { sleep, customConfirm, customAlert } from "./common.js";
|
||||
import { sleep, customConfirm, customAlert, handle403Response, show_message } from "./common.js";
|
||||
|
||||
async function tryInstallCustomNode(event) {
|
||||
let msg = '-= [ComfyUI Manager] extension installation request =-\n\n';
|
||||
@ -42,7 +42,7 @@ async function tryInstallCustomNode(event) {
|
||||
});
|
||||
|
||||
if(response.status == 403) {
|
||||
show_message('This action is not allowed with this security level configuration.');
|
||||
await handle403Response(response);
|
||||
return false;
|
||||
}
|
||||
else if(response.status == 400) {
|
||||
@ -54,7 +54,7 @@ async function tryInstallCustomNode(event) {
|
||||
|
||||
let response = await api.fetchApi("/manager/reboot");
|
||||
if(response.status == 403) {
|
||||
show_message('This action is not allowed with this security level configuration.');
|
||||
await handle403Response(response);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ import { OpenArtShareDialog } from "./comfyui-share-openart.js";
|
||||
import {
|
||||
free_models, install_pip, install_via_git_url, manager_instance,
|
||||
rebootAPI, setManagerInstance, show_message, customAlert, customPrompt,
|
||||
infoToast, showTerminal, setNeedRestart
|
||||
infoToast, showTerminal, setNeedRestart, handle403Response
|
||||
} from "./common.js";
|
||||
import { ComponentBuilderDialog, getPureName, load_components, set_component_policy } from "./components-manager.js";
|
||||
import { CustomNodesManager } from "./custom-nodes-manager.js";
|
||||
@ -753,9 +753,9 @@ async function onQueueStatus(event) {
|
||||
|
||||
const rebootButton = document.getElementById('cm-reboot-button5');
|
||||
rebootButton?.addEventListener("click",
|
||||
function() {
|
||||
if(rebootAPI()) {
|
||||
manager_dialog.close();
|
||||
async function() {
|
||||
if(await rebootAPI()) {
|
||||
manager_instance.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -780,8 +780,13 @@ async function updateAll(update_comfyui) {
|
||||
|
||||
const response = await api.fetchApi(`/manager/queue/update_all?mode=${mode}`);
|
||||
|
||||
if (response.status == 401) {
|
||||
if (response.status == 403) {
|
||||
await handle403Response(response);
|
||||
reset_action_buttons();
|
||||
}
|
||||
else if (response.status == 401) {
|
||||
customAlert('Another task is already in progress. Please stop the ongoing task first.');
|
||||
reset_action_buttons();
|
||||
}
|
||||
else if(response.status == 200) {
|
||||
is_updating = true;
|
||||
@ -1453,6 +1458,31 @@ app.registerExtension({
|
||||
|
||||
load_components();
|
||||
|
||||
// Fetch and show startup alerts (critical errors like outdated ComfyUI)
|
||||
// Poll until extensionManager.toast is ready (set in Vue onMounted)
|
||||
const showStartupAlerts = async () => {
|
||||
let toastWaitCount = 0;
|
||||
const waitForToast = () => {
|
||||
if (window['app']?.extensionManager?.toast) {
|
||||
fetch('/manager/startup_alerts')
|
||||
.then(response => response.ok ? response.json() : [])
|
||||
.then(alerts => {
|
||||
for (const alert of alerts) {
|
||||
customAlert(alert.message);
|
||||
}
|
||||
})
|
||||
.catch(e => console.warn('[ComfyUI-Manager] Failed to fetch startup alerts:', e));
|
||||
} else if (toastWaitCount < 300) { // Max 30 seconds (300 * 100ms)
|
||||
toastWaitCount++;
|
||||
setTimeout(waitForToast, 100);
|
||||
} else {
|
||||
console.warn('[ComfyUI-Manager] Timeout waiting for toast. Startup alerts skipped.');
|
||||
}
|
||||
};
|
||||
waitForToast();
|
||||
};
|
||||
showStartupAlerts();
|
||||
|
||||
const menu = document.querySelector(".comfy-menu");
|
||||
const separator = document.createElement("hr");
|
||||
|
||||
|
||||
40
js/common.js
40
js/common.js
@ -100,6 +100,19 @@ export function show_message(msg) {
|
||||
app.ui.dialog.element.style.zIndex = 1100;
|
||||
}
|
||||
|
||||
export async function handle403Response(res, defaultMessage) {
|
||||
try {
|
||||
const data = await res.json();
|
||||
if(data.error === 'comfyui_outdated') {
|
||||
show_message('ComfyUI version is outdated.<BR>Please update ComfyUI to use Manager normally.');
|
||||
} else {
|
||||
show_message(defaultMessage || 'This action is not allowed with this security level configuration.');
|
||||
}
|
||||
} catch {
|
||||
show_message(defaultMessage || 'This action is not allowed with this security level configuration.');
|
||||
}
|
||||
}
|
||||
|
||||
export async function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
@ -163,20 +176,23 @@ export async function customPrompt(title, message) {
|
||||
}
|
||||
|
||||
|
||||
export function rebootAPI() {
|
||||
export async function rebootAPI() {
|
||||
if ('electronAPI' in window) {
|
||||
window.electronAPI.restartApp();
|
||||
return true;
|
||||
}
|
||||
|
||||
customConfirm("Are you sure you'd like to reboot the server?").then((isConfirmed) => {
|
||||
if (isConfirmed) {
|
||||
try {
|
||||
api.fetchApi("/manager/reboot");
|
||||
const isConfirmed = await customConfirm("Are you sure you'd like to reboot the server?");
|
||||
if (isConfirmed) {
|
||||
try {
|
||||
const response = await api.fetchApi("/manager/reboot");
|
||||
if (response.status == 403) {
|
||||
await handle403Response(response);
|
||||
return false;
|
||||
}
|
||||
catch(exception) {}
|
||||
}
|
||||
});
|
||||
catch(exception) {}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -216,7 +232,7 @@ export async function install_pip(packages) {
|
||||
});
|
||||
|
||||
if(res.status == 403) {
|
||||
show_message('This action is not allowed with this security level configuration.');
|
||||
await handle403Response(res);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -251,7 +267,7 @@ export async function install_via_git_url(url, manager_dialog) {
|
||||
});
|
||||
|
||||
if(res.status == 403) {
|
||||
show_message('This action is not allowed with this security level configuration.');
|
||||
await handle403Response(res);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -262,9 +278,9 @@ export async function install_via_git_url(url, manager_dialog) {
|
||||
const self = this;
|
||||
|
||||
rebootButton.addEventListener("click",
|
||||
function() {
|
||||
if(rebootAPI()) {
|
||||
manager_dialog.close();
|
||||
async function() {
|
||||
if(await rebootAPI()) {
|
||||
manager_instance.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ import {
|
||||
fetchData, md5, icons, show_message, customConfirm, customAlert, customPrompt,
|
||||
sanitizeHTML, infoToast, showTerminal, setNeedRestart,
|
||||
storeColumnWidth, restoreColumnWidth, getTimeAgo, copyText, loadCss,
|
||||
showPopover, hidePopover
|
||||
showPopover, hidePopover, handle403Response
|
||||
} from "./common.js";
|
||||
|
||||
// https://cenfun.github.io/turbogrid/api.html
|
||||
@ -1528,7 +1528,16 @@ export class CustomNodesManager {
|
||||
errorMsg = `'${item.title}': `;
|
||||
|
||||
if(res.status == 403) {
|
||||
errorMsg += `This action is not allowed with this security level configuration.\n`;
|
||||
try {
|
||||
const data = await res.json();
|
||||
if(data.error === 'comfyui_outdated') {
|
||||
errorMsg += `ComfyUI version is outdated. Please update ComfyUI to use Manager normally.\n`;
|
||||
} else {
|
||||
errorMsg += `This action is not allowed with this security level configuration.\n`;
|
||||
}
|
||||
} catch {
|
||||
errorMsg += `This action is not allowed with this security level configuration.\n`;
|
||||
}
|
||||
} else if(res.status == 404) {
|
||||
errorMsg += `With the current security level configuration, only custom nodes from the <B>"default channel"</B> can be installed.\n`;
|
||||
} else {
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { $el } from "../../scripts/ui.js";
|
||||
import {
|
||||
manager_instance, rebootAPI,
|
||||
import {
|
||||
manager_instance, rebootAPI,
|
||||
fetchData, md5, icons, show_message, customAlert, infoToast, showTerminal,
|
||||
storeColumnWidth, restoreColumnWidth, loadCss
|
||||
storeColumnWidth, restoreColumnWidth, loadCss, handle403Response
|
||||
} from "./common.js";
|
||||
import { api } from "../../scripts/api.js";
|
||||
|
||||
@ -477,7 +477,16 @@ export class ModelManager {
|
||||
errorMsg = `'${item.name}': `;
|
||||
|
||||
if(res.status == 403) {
|
||||
errorMsg += `This action is not allowed with this security level configuration.\n`;
|
||||
try {
|
||||
const data = await res.json();
|
||||
if(data.error === 'comfyui_outdated') {
|
||||
errorMsg += `ComfyUI version is outdated. Please update ComfyUI to use Manager normally.\n`;
|
||||
} else {
|
||||
errorMsg += `This action is not allowed with this security level configuration.\n`;
|
||||
}
|
||||
} catch {
|
||||
errorMsg += `This action is not allowed with this security level configuration.\n`;
|
||||
}
|
||||
} else {
|
||||
errorMsg += await res.text() + '\n';
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { api } from "../../scripts/api.js"
|
||||
import { ComfyDialog, $el } from "../../scripts/ui.js";
|
||||
import { manager_instance, rebootAPI, show_message } from "./common.js";
|
||||
import { manager_instance, rebootAPI, show_message, handle403Response } from "./common.js";
|
||||
|
||||
|
||||
async function restore_snapshot(target) {
|
||||
@ -10,7 +10,7 @@ async function restore_snapshot(target) {
|
||||
const response = await api.fetchApi(`/snapshot/restore?target=${target}`, { cache: "no-store" });
|
||||
|
||||
if(response.status == 403) {
|
||||
show_message('This action is not allowed with this security level configuration.');
|
||||
await handle403Response(response);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ async function remove_snapshot(target) {
|
||||
const response = await api.fetchApi(`/snapshot/remove?target=${target}`, { cache: "no-store" });
|
||||
|
||||
if(response.status == 403) {
|
||||
show_message('This action is not allowed with this security level configuration.');
|
||||
await handle403Response(response);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -145,8 +145,8 @@ export class SnapshotManager extends ComfyDialog {
|
||||
if(btn_id) {
|
||||
const rebootButton = document.getElementById(btn_id);
|
||||
const self = this;
|
||||
rebootButton.onclick = function() {
|
||||
if(rebootAPI()) {
|
||||
rebootButton.onclick = async function() {
|
||||
if(await rebootAPI()) {
|
||||
self.close();
|
||||
self.manager_dialog.close();
|
||||
}
|
||||
|
||||
@ -1,5 +1,78 @@
|
||||
{
|
||||
"custom_nodes": [
|
||||
{
|
||||
"author": "HAL-XP",
|
||||
"title": "HALXP-Comfy",
|
||||
"reference": "https://github.com/hal-xp/halxp-comfy",
|
||||
"files": [
|
||||
"https://github.com/hal-xp/halxp-comfy"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A UI suite for ComfyUI including Focus mode and layout enhancements."
|
||||
},
|
||||
{
|
||||
"author": "BuddyBytes",
|
||||
"title": "Smart Resolution Toolkit",
|
||||
"reference": "https://github.com/buddy-bytes/ComfyUI-SmartResolutionToolkit",
|
||||
"files": [
|
||||
"https://github.com/buddy-bytes/ComfyUI-SmartResolutionToolkit"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Resolution picker and latent generator for ComfyUI. Select presets like HD, FullHD, 2K, 4K, 8K with aspect ratios (1:1, 9:16, 4:5, 21:9 etc.) via dropdowns. Automatically snaps width/height to latent-safe multiples of 64. Ideal for EmptyLatentImage, AnimateDiff, ControlNet, video formats, and KSampler workflows. Outputs clean INT values or ready-to-use LATENT tensor."
|
||||
},
|
||||
{
|
||||
"author": "Bharanidharan",
|
||||
"title": "iSeeBetter Node for ComfyUI",
|
||||
"reference": "https://github.com/llikethat/ComfyUI-iseebetter",
|
||||
"files": [
|
||||
"https://github.com/llikethat/ComfyUI-iseebetter"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom Node to implement iSeeBetter upscaling method."
|
||||
},
|
||||
{
|
||||
"author": "Pondowner857",
|
||||
"title": "ComfyUI Remote Workflow Executor",
|
||||
"id": "comfy_Pond_Nodes_V2",
|
||||
"reference": "https://github.com/Pondowner857/comfy_Pond_Nodes_V2",
|
||||
"files": [
|
||||
"https://github.com/Pondowner857/comfy_Pond_Nodes_V2"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Remote workflow executor node - Execute workflows on remote ComfyUI servers. Supports image/text/audio/video input and output."
|
||||
},
|
||||
{
|
||||
"author": "luxdelux7",
|
||||
"title": "Forbidden Vision",
|
||||
"reference": "https://github.com/luxdelux7/ComfyUI-Forbidden-Vision",
|
||||
"files": [
|
||||
"https://github.com/luxdelux7/ComfyUI-Forbidden-Vision"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom face detection and segmentation for ComfyUI with automatic face fixing, intelligent color grading, and iterative refinement. Custom-trained models optimized for realistic, anime, and NSFW content.",
|
||||
"nodename_pattern": "ForbiddenVision"
|
||||
},
|
||||
{
|
||||
"author": "Kazama-Suichiku",
|
||||
"title": "ComfyUI-Meshy",
|
||||
"id": "comfyui-meshy",
|
||||
"reference": "https://github.com/Kazama-Suichiku/ComfyUI-Meshy",
|
||||
"files": [
|
||||
"https://github.com/Kazama-Suichiku/ComfyUI-Meshy"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI-Meshy is a 3D generation extension based on Meshy AI API. It provides Text-to-3D and Image-to-3D capabilities within ComfyUI, allowing you to generate 3D models directly from text prompts or images. Supports multiple AI models (Meshy-4, Meshy-5, Meshy-6) with customizable topology, polygon count, and PBR settings."
|
||||
},
|
||||
{
|
||||
"author": "ah-kun",
|
||||
"title": "ComfyUI-FailSafe-Translate-Node",
|
||||
"reference": "https://github.com/ah-kun/ComfyUI-FailSafe-Translate-Node",
|
||||
"files": [
|
||||
"https://github.com/ah-kun/ComfyUI-FailSafe-Translate-Node"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Fail-safe Google Translate prompt node for ComfyUI (retry + caching)."
|
||||
},
|
||||
{
|
||||
"author": "princepainter",
|
||||
"title": "PainterFLF2V - First/Last Frame Video Enhancer",
|
||||
@ -656,196 +729,6 @@
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI integration for Meta's SAM3 model enabling open-vocabulary image segmentation using natural language text prompts, with automatic model download, geometric refinement, and flexible confidence thresholds."
|
||||
},
|
||||
{
|
||||
"author": "wwzhifeng",
|
||||
"title": "comfyui-jsonprompt",
|
||||
"reference": "https://github.com/wwzhifeng/comfyui-jsonprompt",
|
||||
"files": [
|
||||
"https://github.com/wwzhifeng/comfyui-jsonprompt"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom ComfyUI node that expands structured JSON text into standard prompts for use with models like Gemini, Flux, OpenAI, and Sora. (Description by CC)"
|
||||
},
|
||||
{
|
||||
"author": "StarIICraft",
|
||||
"title": "ComfyUI-Simple-Selector",
|
||||
"reference": "https://github.com/StarIICraft/ComfyUI-Simple-Selector",
|
||||
"files": [
|
||||
"https://github.com/StarIICraft/ComfyUI-Simple-Selector"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Logic control node with 5 universal input ports that checks connections in reverse priority order and outputs the index of the first valid active input, with support for muted nodes and any data type."
|
||||
},
|
||||
{
|
||||
"author": "fr0nky0ng",
|
||||
"title": "ComfyUI-JSON-Prompt",
|
||||
"reference": "https://github.com/fr0nky0ng/ComfyUI-JSON-Prompt",
|
||||
"files": [
|
||||
"https://github.com/fr0nky0ng/ComfyUI-JSON-Prompt"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom node for ComfyUI that generates JSON prompts from natural language descriptions to improve text-to-image generation quality. Supports local LLM integration via Ollama or Google Gemini API."
|
||||
},
|
||||
{
|
||||
"author": "EricRollei",
|
||||
"title": "Eric_Image_Processing_Nodes",
|
||||
"reference": "https://github.com/EricRollei/Eric_Image_Processing_Nodes",
|
||||
"files": [
|
||||
"https://github.com/EricRollei/Eric_Image_Processing_Nodes"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A comprehensive collection of advanced image processing nodes for ComfyUI, featuring state-of-the-art denoising, enhancement, and restoration techniques with GPU acceleration and specialized film grain processing."
|
||||
},
|
||||
{
|
||||
"author": "huyl3-cpu",
|
||||
"title": "comfyui-huyl2-nodes",
|
||||
"reference": "https://github.com/huyl3-cpu/comfyui-sortlist",
|
||||
"files": [
|
||||
"https://github.com/huyl3-cpu/comfyui-sortlist"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Custom utility nodes for ComfyUI by huyl2 (sort list v2, etc.)"
|
||||
},
|
||||
{
|
||||
"author": "7BEII",
|
||||
"title": "comfyui-PD_comfy-api-node",
|
||||
"reference": "https://github.com/7BEII/comfyui-PD_comfy-api-node",
|
||||
"files": [
|
||||
"https://github.com/7BEII/comfyui-PD_comfy-api-node"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI custom node suite integrating multiple AI image generation APIs (Gemini, Flux.1 Kontext Pro) with unified authentication via ComfyUI API Key and real-time cost tracking. (Description by CC)"
|
||||
},
|
||||
{
|
||||
"author": "wallen0322",
|
||||
"title": "ComfyUI-AE-Animation",
|
||||
"reference": "https://github.com/wallen0322/ComfyUI-AE-Animation",
|
||||
"files": [
|
||||
"https://github.com/wallen0322/ComfyUI-AE-Animation"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "After Effects-style animation nodes for ComfyUI with timeline-based keyframe control, layer management, and real-time preview rendering. (Description by CC)"
|
||||
},
|
||||
{
|
||||
"author": "wallen0322",
|
||||
"title": "ComfyUI-TTM-WAN22",
|
||||
"reference": "https://github.com/wallen0322/ComfyUI-TTM-WAN22",
|
||||
"files": [
|
||||
"https://github.com/wallen0322/ComfyUI-TTM-WAN22"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "TTM (Time-to-Move) node for ComfyUI enabling motion-controlled video generation with Wan2.2 models using dual-clock denoising for independent background and object animation control."
|
||||
},
|
||||
{
|
||||
"author": "swan7-py",
|
||||
"title": "ComfyUI-ImageAlphaCrop",
|
||||
"reference": "https://github.com/swan7-py/ComfyUI-ImageAlphaCrop",
|
||||
"files": [
|
||||
"https://github.com/swan7-py/ComfyUI-ImageAlphaCrop"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI plugin for automatically cropping transparent alpha channel borders from images - ideal for processing logos and icons. Supports batch processing with adjustable padding and alpha threshold. (Description by CC)"
|
||||
},
|
||||
{
|
||||
"author": "was",
|
||||
"title": "WAS LMStudio Easy-Query",
|
||||
"reference": "https://github.com/WASasquatch/ComfyUI_LMStudio_EasyQuery",
|
||||
"files": [
|
||||
"https://github.com/WASasquatch/ComfyUI_LMStudio_EasyQuery"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "LM Studio calls with image support and easy task directions."
|
||||
},
|
||||
{
|
||||
"author": "PozzettiAndrea",
|
||||
"title": "ComfyUI-AnyTop",
|
||||
"reference": "https://github.com/PozzettiAndrea/ComfyUI-AnyTop",
|
||||
"files": [
|
||||
"https://github.com/PozzettiAndrea/ComfyUI-AnyTop"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Standalone ComfyUI custom nodes for AnyTop - Universal Motion Generation for Any Skeleton Topology."
|
||||
},
|
||||
{
|
||||
"author": "IamCreateAI",
|
||||
"title": "ComfyUI-Animon",
|
||||
"reference": "https://github.com/IamCreateAI/ComfyUI-Animon",
|
||||
"files": [
|
||||
"https://github.com/IamCreateAI/ComfyUI-Animon"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI nodes for [Animon Platform](https://platform.animon.ai/), a comprehensive API service offering a variety of image and video generation models."
|
||||
},
|
||||
{
|
||||
"author": "neonr0",
|
||||
"title": "ComfyUI-PixelConstrainedScaler",
|
||||
"reference": "https://github.com/neonr-0/ComfyUI-PixelConstrainedScaler",
|
||||
"files": [
|
||||
"https://github.com/neonr-0/ComfyUI-PixelConstrainedScaler"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Smart upscaling with pixel-budget awareness while preserving native aspect ratios. Ideal for Image to Image (I2I) and Image to Video (I2V) workflows!"
|
||||
},
|
||||
{
|
||||
"author": "slahiri",
|
||||
"title": "ComfyUI-AI-Photography-Toolkit",
|
||||
"reference": "https://github.com/slahiri/ComfyUI-AI-Photography-Toolkit",
|
||||
"files": [
|
||||
"https://github.com/slahiri/ComfyUI-AI-Photography-Toolkit"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A collection of AI-powered photography and image generation tools for ComfyUI, featuring the SID_AIPromptGenerator node that uses Anthropic's Claude API to analyze images and generate optimized prompts for various image generation models."
|
||||
},
|
||||
{
|
||||
"author": "wzyfromhust",
|
||||
"title": "ComfyUI_SAM2UltraV2",
|
||||
"reference": "https://github.com/wzyfromhust/ComfyUI_SAM2UltraV2",
|
||||
"files": [
|
||||
"https://github.com/wzyfromhust/ComfyUI_SAM2UltraV2"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "A fully modular and high-performance implementation of SAM2 (Segment Anything Model 2) for ComfyUI with dual-prompt support, negative point sampling, and upper body segmentation."
|
||||
},
|
||||
{
|
||||
"author": "cedarconnor",
|
||||
"title": "ComfyUI-DreamCube",
|
||||
"reference": "https://github.com/cedarconnor/ComfyUI-DreamCube",
|
||||
"files": [
|
||||
"https://github.com/cedarconnor/ComfyUI-DreamCube"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "360° panoramic depth estimation with multi-plane synchronization for ComfyUI, featuring equirectangular-cubemap transformations, cross-face consistency, and boundary blending for seamless depth maps."
|
||||
},
|
||||
{
|
||||
"author": "dowa-git",
|
||||
"title": "comfyui-dowa",
|
||||
"reference": "https://github.com/dowa-git/comfyui-dowa",
|
||||
"files": [
|
||||
"https://github.com/dowa-git/comfyui-dowa"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "Professional navigation bar widget for ComfyUI with JWT-based user authentication, workflow templates, and team collaboration features in a purple gradient design."
|
||||
},
|
||||
{
|
||||
"author": "fuselayer",
|
||||
"title": "comfyui-lite-tracker",
|
||||
"reference": "https://github.com/fuselayer/comfyui-lite-tracker",
|
||||
"files": [
|
||||
"https://github.com/fuselayer/comfyui-lite-tracker"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI custom nodes for LiteTracker, a fast and efficient point tracking model for videos with load model, track, and grid editor nodes."
|
||||
},
|
||||
{
|
||||
"author": "yichengup",
|
||||
"title": "ComfyUI-YCNodes_Toolkit",
|
||||
"reference": "https://github.com/yichengup/ComfyUI-YCNodes_Toolkit",
|
||||
"files": [
|
||||
"https://github.com/yichengup/ComfyUI-YCNodes_Toolkit"
|
||||
],
|
||||
"install_type": "git-clone",
|
||||
"description": "ComfyUI toolkit with custom nodes for BBox canvas visualization, image brush mask drawing, and coordinate annotation for debugging and external data bridging. (Description by CC)"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -2831,8 +2831,8 @@
|
||||
"GoogleImagenEditNode",
|
||||
"GoogleImagenNode",
|
||||
"NanoBananaNode",
|
||||
"Veo3VideoGenerator",
|
||||
"VeoGeminiVideoGenerator"
|
||||
"VeoGeminiVideoGenerator",
|
||||
"VeoVertexVideoGenerator"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-ExternalAPI-Helpers"
|
||||
@ -6287,6 +6287,7 @@
|
||||
"Multi-LoRA Loader Qwen",
|
||||
"Multi-LoRA Loader Wan-i2v",
|
||||
"Multi-LoRA Loader Wan-t2v",
|
||||
"Multi-LoRA Loader Z-Image",
|
||||
"Multi-LoRA Loader [PLATFORM_NAME]",
|
||||
"Multi-LoRA Loader v02",
|
||||
"MyCustomNode",
|
||||
@ -6306,6 +6307,7 @@
|
||||
],
|
||||
"https://github.com/EricRollei/Comfy_HunyuanImage3": [
|
||||
[
|
||||
"HunyuanImage3ClearDownstream",
|
||||
"HunyuanImage3ForceUnload",
|
||||
"HunyuanImage3FullGPULoader",
|
||||
"HunyuanImage3FullLoader",
|
||||
@ -13828,10 +13830,12 @@
|
||||
"GeomPackFixNormals",
|
||||
"GeomPackFixSelfIntersectionsByPerturbation",
|
||||
"GeomPackFixSelfIntersectionsByRemoval",
|
||||
"GeomPackGetMeshFilename",
|
||||
"GeomPackLoadMesh",
|
||||
"GeomPackLoadMeshBatch",
|
||||
"GeomPackLoadMeshBlend",
|
||||
"GeomPackLoadMeshFBX",
|
||||
"GeomPackMergeVertices",
|
||||
"GeomPackMeshFromSkeleton",
|
||||
"GeomPackMeshInfo",
|
||||
"GeomPackMeshQuality",
|
||||
@ -13848,6 +13852,7 @@
|
||||
"GeomPackRemesh",
|
||||
"GeomPackRemeshSelfIntersections",
|
||||
"GeomPackRemeshWithTexture",
|
||||
"GeomPackRemoveDegenerateFaces",
|
||||
"GeomPackSaveMesh",
|
||||
"GeomPackSaveMeshBatch",
|
||||
"GeomPackTextureToGeometry",
|
||||
@ -14400,6 +14405,8 @@
|
||||
],
|
||||
"https://github.com/Rizzlord/ComfyUI-RizzNodes": [
|
||||
[
|
||||
"BatchImagesToGrid",
|
||||
"LoadMultiviewImages",
|
||||
"RizzAlphaMargin",
|
||||
"RizzBatchImageLoader",
|
||||
"RizzBlur",
|
||||
@ -14414,7 +14421,10 @@
|
||||
"RizzModelBatchLoader",
|
||||
"RizzPasteAndUnscale",
|
||||
"RizzUpscaleImageBatch",
|
||||
"SimplifyMesh"
|
||||
"SaveMultiviewImages",
|
||||
"SimplifyMesh",
|
||||
"SplitImageBatch",
|
||||
"VideoSecondsToLength"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-RizzNodes"
|
||||
@ -18907,6 +18917,7 @@
|
||||
],
|
||||
"https://github.com/WingeD123/ComfyUI_QwenVL_PromptCaption": [
|
||||
[
|
||||
"Ovis25Run",
|
||||
"Qwen25Caption",
|
||||
"Qwen25CaptionBatch",
|
||||
"Qwen3Caption",
|
||||
@ -23320,6 +23331,7 @@
|
||||
],
|
||||
"https://github.com/bradsec/ComfyUI_StringEssentials": [
|
||||
[
|
||||
"StringConditionalAppend",
|
||||
"StringMultiReplace",
|
||||
"StringPreview",
|
||||
"StringStrip",
|
||||
@ -26204,6 +26216,11 @@
|
||||
"KlingImageGenerationNode",
|
||||
"KlingLipSyncAudioToVideoNode",
|
||||
"KlingLipSyncTextToVideoNode",
|
||||
"KlingOmniProEditVideoNode",
|
||||
"KlingOmniProFirstLastFrameNode",
|
||||
"KlingOmniProImageToVideoNode",
|
||||
"KlingOmniProTextToVideoNode",
|
||||
"KlingOmniProVideoToVideoNode",
|
||||
"KlingSingleImageVideoEffectNode",
|
||||
"KlingStartEndFrameNode",
|
||||
"KlingTextToVideoNode",
|
||||
@ -29102,6 +29119,7 @@
|
||||
"HunyuanVideoPromptExpander",
|
||||
"HunyuanVideoTextEncoder",
|
||||
"HunyuanVideoVisionLoader",
|
||||
"LLMOutputParser",
|
||||
"PromptKeyFilter",
|
||||
"QwenDebugController",
|
||||
"QwenEliGenEntityControl",
|
||||
@ -29126,9 +29144,11 @@
|
||||
"QwenVLTextEncoder",
|
||||
"QwenVLTextEncoderAdvanced",
|
||||
"TemplateInfluenceAnalyzer",
|
||||
"ZImageEmptyLatent",
|
||||
"ZImageTextEncoder",
|
||||
"ZImageTextEncoderSimple",
|
||||
"ZImageTurnBuilder"
|
||||
"ZImageTurnBuilder",
|
||||
"ZImageWanVAEDecode"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI-QwenImageWanBridge"
|
||||
@ -30634,6 +30654,10 @@
|
||||
"Kling21Pro_fal",
|
||||
"Kling25TurboPro_fal",
|
||||
"KlingMaster_fal",
|
||||
"KlingOmniImageToVideo_fal",
|
||||
"KlingOmniReferenceToVideo_fal",
|
||||
"KlingOmniVideoToVideoEdit_fal",
|
||||
"KlingOmniVideoToVideoReference_fal",
|
||||
"KlingPro10_fal",
|
||||
"KlingPro16_fal",
|
||||
"Kling_fal",
|
||||
@ -31806,10 +31830,9 @@
|
||||
],
|
||||
"https://github.com/hobinrude/ComfyUI_DWposeDeluxe": [
|
||||
[
|
||||
"DWposeKeypointConverter",
|
||||
"DWposeWeightOptions",
|
||||
"FrameNumberNode",
|
||||
"KeypointConverter",
|
||||
"LoadPoseKeypoints",
|
||||
"WeightOptions"
|
||||
],
|
||||
{
|
||||
@ -36486,7 +36509,9 @@
|
||||
[
|
||||
"QwenImageEditScale",
|
||||
"QwenImageEditSimpleScale",
|
||||
"TextEncodeQwenImageEditAdv"
|
||||
"TextEncodeQwenImageEditAdv",
|
||||
"TextEncodeQwenImageEditInfAdv",
|
||||
"TextEncodeQwenImageEditPlusAdv"
|
||||
],
|
||||
{
|
||||
"title_aux": "comfyui_qwen_image_edit_adv"
|
||||
@ -38480,6 +38505,7 @@
|
||||
"EasyResize",
|
||||
"EasyWan22Prompt",
|
||||
"Easy_Version",
|
||||
"KoolookLoadCameraPosesAbsolute",
|
||||
"easy_ImageBatch"
|
||||
],
|
||||
{
|
||||
@ -42821,6 +42847,12 @@
|
||||
"WaveSpeedAI Flux Kontext Max",
|
||||
"WaveSpeedAI Flux Kontext Pro",
|
||||
"WaveSpeedAI Google Nano Banana Edit",
|
||||
"WaveSpeedAI Google Nano Banana Pro Edit",
|
||||
"WaveSpeedAI Google Nano Banana Pro Edit Multi",
|
||||
"WaveSpeedAI Google Nano Banana Pro Edit Ultra",
|
||||
"WaveSpeedAI Google Nano Banana Pro Text to Image",
|
||||
"WaveSpeedAI Google Nano Banana Pro Text to Image Multi",
|
||||
"WaveSpeedAI Google Nano Banana Pro Text to Image Ultra",
|
||||
"WaveSpeedAI Google Nano Banana Text to Image",
|
||||
"WaveSpeedAI Google VEO 3.1 Fast Image-to-Video",
|
||||
"WaveSpeedAI Google VEO 3.1 Fast Text-to-Video",
|
||||
@ -45260,8 +45292,11 @@
|
||||
],
|
||||
"https://github.com/smthemex/ComfyUI_DiffuEraser": [
|
||||
[
|
||||
"DiffuEraserLoader",
|
||||
"DiffuEraserSampler"
|
||||
"DiffuEraser_Loader",
|
||||
"DiffuEraser_PreData",
|
||||
"DiffuEraser_Sampler",
|
||||
"Propainter_Loader",
|
||||
"Propainter_Sampler"
|
||||
],
|
||||
{
|
||||
"title_aux": "ComfyUI_DiffuEraser"
|
||||
|
||||
@ -85,7 +85,15 @@ cm_global.register_api('cm.is_import_failed_extension', is_import_failed_extensi
|
||||
comfyui_manager_path = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
custom_nodes_base_path = folder_paths.get_folder_paths('custom_nodes')[0]
|
||||
manager_files_path = os.path.abspath(os.path.join(folder_paths.get_user_directory(), 'default', 'ComfyUI-Manager'))
|
||||
|
||||
# Check for System User API availability (PR #10966)
|
||||
_has_system_user_api = hasattr(folder_paths, 'get_system_user_directory')
|
||||
|
||||
if _has_system_user_api:
|
||||
manager_files_path = os.path.abspath(os.path.join(folder_paths.get_user_directory(), '__manager'))
|
||||
else:
|
||||
manager_files_path = os.path.abspath(os.path.join(folder_paths.get_user_directory(), 'default', 'ComfyUI-Manager'))
|
||||
|
||||
manager_pip_overrides_path = os.path.join(manager_files_path, "pip_overrides.json")
|
||||
manager_pip_blacklist_path = os.path.join(manager_files_path, "pip_blacklist.list")
|
||||
restore_snapshot_path = os.path.join(manager_files_path, "startup-scripts", "restore-snapshot.json")
|
||||
@ -516,7 +524,8 @@ check_bypass_ssl()
|
||||
|
||||
# Perform install
|
||||
processed_install = set()
|
||||
script_list_path = os.path.join(folder_paths.user_directory, "default", "ComfyUI-Manager", "startup-scripts", "install-scripts.txt")
|
||||
# Use manager_files_path for consistency (fixes path inconsistency bug)
|
||||
script_list_path = os.path.join(manager_files_path, "startup-scripts", "install-scripts.txt")
|
||||
pip_fixer = manager_util.PIPFixer(manager_util.get_installed_packages(), comfy_path, manager_files_path)
|
||||
|
||||
|
||||
@ -793,7 +802,11 @@ def execute_startup_script():
|
||||
|
||||
|
||||
# Check if script_list_path exists
|
||||
if os.path.exists(script_list_path):
|
||||
# Block startup-scripts on old ComfyUI (security measure)
|
||||
if not _has_system_user_api:
|
||||
if os.path.exists(script_list_path):
|
||||
print("[ComfyUI-Manager] Startup scripts blocked on old ComfyUI version.")
|
||||
elif os.path.exists(script_list_path):
|
||||
execute_startup_script()
|
||||
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "comfyui-manager"
|
||||
description = "ComfyUI-Manager provides features to install and manage custom nodes for ComfyUI, as well as various functionalities to assist with ComfyUI."
|
||||
version = "3.37.2"
|
||||
version = "3.38"
|
||||
license = { file = "LICENSE.txt" }
|
||||
dependencies = ["GitPython", "PyGithub", "matrix-nio", "transformers", "huggingface-hub>0.20", "typer", "rich", "typing-extensions", "toml", "uv", "chardet"]
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user