comfygit-core 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- comfygit_core/analyzers/custom_node_scanner.py +109 -0
- comfygit_core/analyzers/git_change_parser.py +156 -0
- comfygit_core/analyzers/model_scanner.py +318 -0
- comfygit_core/analyzers/node_classifier.py +58 -0
- comfygit_core/analyzers/node_git_analyzer.py +77 -0
- comfygit_core/analyzers/status_scanner.py +362 -0
- comfygit_core/analyzers/workflow_dependency_parser.py +143 -0
- comfygit_core/caching/__init__.py +16 -0
- comfygit_core/caching/api_cache.py +210 -0
- comfygit_core/caching/base.py +212 -0
- comfygit_core/caching/comfyui_cache.py +100 -0
- comfygit_core/caching/custom_node_cache.py +320 -0
- comfygit_core/caching/workflow_cache.py +797 -0
- comfygit_core/clients/__init__.py +4 -0
- comfygit_core/clients/civitai_client.py +412 -0
- comfygit_core/clients/github_client.py +349 -0
- comfygit_core/clients/registry_client.py +230 -0
- comfygit_core/configs/comfyui_builtin_nodes.py +1614 -0
- comfygit_core/configs/comfyui_models.py +62 -0
- comfygit_core/configs/model_config.py +151 -0
- comfygit_core/constants.py +82 -0
- comfygit_core/core/environment.py +1635 -0
- comfygit_core/core/workspace.py +898 -0
- comfygit_core/factories/environment_factory.py +419 -0
- comfygit_core/factories/uv_factory.py +61 -0
- comfygit_core/factories/workspace_factory.py +109 -0
- comfygit_core/infrastructure/sqlite_manager.py +156 -0
- comfygit_core/integrations/__init__.py +7 -0
- comfygit_core/integrations/uv_command.py +318 -0
- comfygit_core/logging/logging_config.py +15 -0
- comfygit_core/managers/environment_git_orchestrator.py +316 -0
- comfygit_core/managers/environment_model_manager.py +296 -0
- comfygit_core/managers/export_import_manager.py +116 -0
- comfygit_core/managers/git_manager.py +667 -0
- comfygit_core/managers/model_download_manager.py +252 -0
- comfygit_core/managers/model_symlink_manager.py +166 -0
- comfygit_core/managers/node_manager.py +1378 -0
- comfygit_core/managers/pyproject_manager.py +1321 -0
- comfygit_core/managers/user_content_symlink_manager.py +436 -0
- comfygit_core/managers/uv_project_manager.py +569 -0
- comfygit_core/managers/workflow_manager.py +1944 -0
- comfygit_core/models/civitai.py +432 -0
- comfygit_core/models/commit.py +18 -0
- comfygit_core/models/environment.py +293 -0
- comfygit_core/models/exceptions.py +378 -0
- comfygit_core/models/manifest.py +132 -0
- comfygit_core/models/node_mapping.py +201 -0
- comfygit_core/models/protocols.py +248 -0
- comfygit_core/models/registry.py +63 -0
- comfygit_core/models/shared.py +356 -0
- comfygit_core/models/sync.py +42 -0
- comfygit_core/models/system.py +204 -0
- comfygit_core/models/workflow.py +914 -0
- comfygit_core/models/workspace_config.py +71 -0
- comfygit_core/py.typed +0 -0
- comfygit_core/repositories/migrate_paths.py +49 -0
- comfygit_core/repositories/model_repository.py +958 -0
- comfygit_core/repositories/node_mappings_repository.py +246 -0
- comfygit_core/repositories/workflow_repository.py +57 -0
- comfygit_core/repositories/workspace_config_repository.py +121 -0
- comfygit_core/resolvers/global_node_resolver.py +459 -0
- comfygit_core/resolvers/model_resolver.py +250 -0
- comfygit_core/services/import_analyzer.py +218 -0
- comfygit_core/services/model_downloader.py +422 -0
- comfygit_core/services/node_lookup_service.py +251 -0
- comfygit_core/services/registry_data_manager.py +161 -0
- comfygit_core/strategies/__init__.py +4 -0
- comfygit_core/strategies/auto.py +72 -0
- comfygit_core/strategies/confirmation.py +69 -0
- comfygit_core/utils/comfyui_ops.py +125 -0
- comfygit_core/utils/common.py +164 -0
- comfygit_core/utils/conflict_parser.py +232 -0
- comfygit_core/utils/dependency_parser.py +231 -0
- comfygit_core/utils/download.py +216 -0
- comfygit_core/utils/environment_cleanup.py +111 -0
- comfygit_core/utils/filesystem.py +178 -0
- comfygit_core/utils/git.py +1184 -0
- comfygit_core/utils/input_signature.py +145 -0
- comfygit_core/utils/model_categories.py +52 -0
- comfygit_core/utils/pytorch.py +71 -0
- comfygit_core/utils/requirements.py +211 -0
- comfygit_core/utils/retry.py +242 -0
- comfygit_core/utils/symlink_utils.py +119 -0
- comfygit_core/utils/system_detector.py +258 -0
- comfygit_core/utils/uuid.py +28 -0
- comfygit_core/utils/uv_error_handler.py +158 -0
- comfygit_core/utils/version.py +73 -0
- comfygit_core/utils/workflow_hash.py +90 -0
- comfygit_core/validation/resolution_tester.py +297 -0
- comfygit_core-0.2.0.dist-info/METADATA +939 -0
- comfygit_core-0.2.0.dist-info/RECORD +93 -0
- comfygit_core-0.2.0.dist-info/WHEEL +4 -0
- comfygit_core-0.2.0.dist-info/licenses/LICENSE.txt +661 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Default ComfyUI models configuration"""
|
|
2
|
+
|
|
3
|
+
COMFYUI_MODELS_CONFIG = {
|
|
4
|
+
"version": "2024.1",
|
|
5
|
+
"default_extensions": [
|
|
6
|
+
".ckpt",
|
|
7
|
+
".pt",
|
|
8
|
+
".pth",
|
|
9
|
+
".pt2",
|
|
10
|
+
".bin",
|
|
11
|
+
".safetensors",
|
|
12
|
+
".pkl",
|
|
13
|
+
".sft",
|
|
14
|
+
],
|
|
15
|
+
"standard_directories": [
|
|
16
|
+
"audio_encoders",
|
|
17
|
+
"checkpoints",
|
|
18
|
+
"clip",
|
|
19
|
+
"clip_vision",
|
|
20
|
+
"configs",
|
|
21
|
+
"controlnet",
|
|
22
|
+
"diffusers",
|
|
23
|
+
"diffusion_models",
|
|
24
|
+
"embeddings",
|
|
25
|
+
"gligen",
|
|
26
|
+
"hypernetworks",
|
|
27
|
+
"loras",
|
|
28
|
+
"model_patches",
|
|
29
|
+
"photomaker",
|
|
30
|
+
"style_models",
|
|
31
|
+
"text_encoders",
|
|
32
|
+
"unet",
|
|
33
|
+
"upscale_models",
|
|
34
|
+
"vae",
|
|
35
|
+
"vae_approx",
|
|
36
|
+
],
|
|
37
|
+
"directory_overrides": {"configs": {"extensions": [".yaml", ".yml", ".json"]}},
|
|
38
|
+
"node_directory_mappings": {
|
|
39
|
+
"CheckpointLoaderSimple": ["checkpoints"],
|
|
40
|
+
"CheckpointLoader": ["checkpoints", "configs"],
|
|
41
|
+
"unCLIPCheckpointLoader": ["checkpoints"],
|
|
42
|
+
"ImageOnlyCheckpointLoader": ["checkpoints"],
|
|
43
|
+
"VAELoader": ["vae", "vae_approx"],
|
|
44
|
+
"LoraLoader": ["loras"],
|
|
45
|
+
"LoraLoaderModelOnly": ["loras"],
|
|
46
|
+
"CLIPLoader": ["clip"],
|
|
47
|
+
"DualCLIPLoader": ["clip"],
|
|
48
|
+
"TripleCLIPLoader": ["clip"],
|
|
49
|
+
"QuadrupleCLIPLoader": ["clip"],
|
|
50
|
+
"UNETLoader": ["diffusion_models"],
|
|
51
|
+
"CLIPVisionLoader": ["clip_vision"],
|
|
52
|
+
"ControlNetLoader": ["controlnet"],
|
|
53
|
+
"DiffControlNetLoader": ["controlnet"],
|
|
54
|
+
"StyleModelLoader": ["style_models"],
|
|
55
|
+
"UpscaleModelLoader": ["upscale_models"],
|
|
56
|
+
"GLIGENLoader": ["gligen"],
|
|
57
|
+
"HypernetworkLoader": ["hypernetworks"],
|
|
58
|
+
"PhotoMakerLoader": ["photomaker"],
|
|
59
|
+
"DiffusersLoader": ["diffusers"],
|
|
60
|
+
},
|
|
61
|
+
"node_widget_indices": {"CheckpointLoader": 1},
|
|
62
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"""Model configuration loader and utilities."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from .comfyui_models import COMFYUI_MODELS_CONFIG
|
|
9
|
+
from ..logging.logging_config import get_logger
|
|
10
|
+
|
|
11
|
+
logger = get_logger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class ModelConfig:
|
|
16
|
+
"""ComfyUI model configuration."""
|
|
17
|
+
version: str
|
|
18
|
+
default_extensions: list[str]
|
|
19
|
+
standard_directories: list[str]
|
|
20
|
+
directory_overrides: dict[str, dict[str, Any]]
|
|
21
|
+
node_directory_mappings: dict[str, list[str]]
|
|
22
|
+
node_widget_indices: dict[str, int]
|
|
23
|
+
|
|
24
|
+
@classmethod
|
|
25
|
+
def load(cls, config_path: Path | None = None) -> "ModelConfig":
|
|
26
|
+
"""Load model configuration from file.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
config_path: Path to config file, or None to use default
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
ModelConfig instance
|
|
33
|
+
"""
|
|
34
|
+
data = {}
|
|
35
|
+
if config_path is None:
|
|
36
|
+
# Load hardcoded config (fallback)
|
|
37
|
+
data = COMFYUI_MODELS_CONFIG
|
|
38
|
+
else:
|
|
39
|
+
if not config_path.exists():
|
|
40
|
+
raise FileNotFoundError(f"Model config file not found: {config_path}")
|
|
41
|
+
try:
|
|
42
|
+
with open(config_path, 'r', encoding='utf-8') as f:
|
|
43
|
+
data = json.load(f)
|
|
44
|
+
except Exception as e:
|
|
45
|
+
logger.error(f"Failed to load model config from {config_path}: {e}")
|
|
46
|
+
raise
|
|
47
|
+
|
|
48
|
+
return cls(
|
|
49
|
+
version=data.get("version", "unknown"),
|
|
50
|
+
default_extensions=data.get("default_extensions", []),
|
|
51
|
+
standard_directories=data.get("standard_directories", []),
|
|
52
|
+
directory_overrides=data.get("directory_overrides", {}),
|
|
53
|
+
node_directory_mappings=data.get("node_directory_mappings", {}),
|
|
54
|
+
node_widget_indices=data.get("node_widget_indices", {})
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def get_extensions_for_directory(self, directory: str) -> list[str]:
|
|
58
|
+
"""Get file extensions for a specific directory.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
directory: Directory name (e.g., "checkpoints")
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
List of supported extensions for this directory
|
|
65
|
+
"""
|
|
66
|
+
if directory in self.directory_overrides:
|
|
67
|
+
override = self.directory_overrides[directory]
|
|
68
|
+
if "extensions" in override:
|
|
69
|
+
return override["extensions"]
|
|
70
|
+
|
|
71
|
+
return self.default_extensions
|
|
72
|
+
|
|
73
|
+
def is_standard_directory(self, directory: str) -> bool:
|
|
74
|
+
"""Check if a directory is a standard ComfyUI directory.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
directory: Directory name to check
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
True if it's a standard directory, False for custom
|
|
81
|
+
"""
|
|
82
|
+
return directory in self.standard_directories
|
|
83
|
+
|
|
84
|
+
def is_model_file(self, file_path: Path) -> bool:
|
|
85
|
+
"""Check if a file is a potential model file based on extension.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
file_path: Path to file to check
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
True if file has a model extension
|
|
92
|
+
"""
|
|
93
|
+
extension = file_path.suffix.lower()
|
|
94
|
+
|
|
95
|
+
# Get directory from path to check for specific extensions
|
|
96
|
+
parts = file_path.parts
|
|
97
|
+
for part in parts:
|
|
98
|
+
if self.is_standard_directory(part):
|
|
99
|
+
return extension in self.get_extensions_for_directory(part)
|
|
100
|
+
|
|
101
|
+
# Default to checking against default extensions
|
|
102
|
+
return extension in self.default_extensions
|
|
103
|
+
|
|
104
|
+
def get_directories_for_node(self, node_type: str) -> list[str]:
|
|
105
|
+
"""Get model directories for a node type.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
node_type: ComfyUI node type (e.g., "LoraLoader")
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
List of directories this node type loads from
|
|
112
|
+
"""
|
|
113
|
+
return self.node_directory_mappings.get(node_type, [])
|
|
114
|
+
|
|
115
|
+
def get_widget_index_for_node(self, node_type: str) -> int:
|
|
116
|
+
"""Get widget index containing model path for a node type.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
node_type: ComfyUI node type
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
Index in widgets_values containing the model path (defaults to 0)
|
|
123
|
+
"""
|
|
124
|
+
return self.node_widget_indices.get(node_type, 0)
|
|
125
|
+
|
|
126
|
+
def is_model_loader_node(self, node_type: str) -> bool:
|
|
127
|
+
"""Check if a node type is a known model loader.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
node_type: ComfyUI node type
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
True if node type loads models
|
|
134
|
+
"""
|
|
135
|
+
return node_type in self.node_directory_mappings
|
|
136
|
+
|
|
137
|
+
def reconstruct_model_path(self, node_type: str, widget_value: str) -> list[str]:
|
|
138
|
+
"""Reconstruct full model paths from node type and widget value.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
node_type: ComfyUI node type
|
|
142
|
+
widget_value: Value from node's widgets_values
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
List of possible full relative paths
|
|
146
|
+
"""
|
|
147
|
+
directories = self.get_directories_for_node(node_type)
|
|
148
|
+
if not directories:
|
|
149
|
+
return []
|
|
150
|
+
|
|
151
|
+
return [f"{directory}/{widget_value}" for directory in directories]
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""Constants and configuration for ComfyUI environment detection."""
|
|
2
|
+
|
|
3
|
+
# PyTorch-related packages that need special handling
|
|
4
|
+
PYTORCH_PACKAGE_NAMES = {
|
|
5
|
+
# Core PyTorch packages
|
|
6
|
+
'torch', 'torchvision', 'torchaudio',
|
|
7
|
+
|
|
8
|
+
# Triton packages (PyTorch's fused-kernel compiler)
|
|
9
|
+
'triton', 'triton-windows',
|
|
10
|
+
|
|
11
|
+
# NVIDIA CUDA packages
|
|
12
|
+
'nvidia-cublas-cu11', 'nvidia-cublas-cu12',
|
|
13
|
+
'nvidia-cuda-runtime-cu11', 'nvidia-cuda-runtime-cu12',
|
|
14
|
+
'nvidia-cuda-nvrtc-cu11', 'nvidia-cuda-nvrtc-cu12',
|
|
15
|
+
'nvidia-cudnn-cu11', 'nvidia-cudnn-cu12',
|
|
16
|
+
'nvidia-cufft-cu11', 'nvidia-cufft-cu12',
|
|
17
|
+
'nvidia-curand-cu11', 'nvidia-curand-cu12',
|
|
18
|
+
'nvidia-cusolver-cu11', 'nvidia-cusolver-cu12',
|
|
19
|
+
'nvidia-cusparse-cu11', 'nvidia-cusparse-cu12',
|
|
20
|
+
'nvidia-nccl-cu11', 'nvidia-nccl-cu12',
|
|
21
|
+
'nvidia-nvtx-cu11', 'nvidia-nvtx-cu12',
|
|
22
|
+
|
|
23
|
+
# New CUDA packages in PyTorch 2.6+
|
|
24
|
+
'nvidia-cuda-cupti-cu11', 'nvidia-cuda-cupti-cu12', # CUPTI (profiler)
|
|
25
|
+
'nvidia-cufile-cu11', 'nvidia-cufile-cu12', # cuFile (GPUDirect Storage)
|
|
26
|
+
'nvidia-cusparselt-cu11', 'nvidia-cusparselt-cu12', # structured-sparse LT
|
|
27
|
+
'nvidia-nvjitlink-cu11', 'nvidia-nvjitlink-cu12', # NVJitLink
|
|
28
|
+
|
|
29
|
+
# NOTE: nvidia-ml-py and nvidia-ml-py3 are NOT included
|
|
30
|
+
# These are optional NVML bindings for monitoring that PyTorch doesn't depend on
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
# Blacklist of directory names that should not be treated as custom nodes
|
|
34
|
+
CUSTOM_NODES_BLACKLIST = {
|
|
35
|
+
'__pycache__',
|
|
36
|
+
'.pytest_cache',
|
|
37
|
+
'.mypy_cache',
|
|
38
|
+
'.tox',
|
|
39
|
+
'node_modules',
|
|
40
|
+
'.vscode',
|
|
41
|
+
'.idea',
|
|
42
|
+
'venv',
|
|
43
|
+
'.venv',
|
|
44
|
+
'env',
|
|
45
|
+
'.env',
|
|
46
|
+
'build',
|
|
47
|
+
'dist',
|
|
48
|
+
'.DS_Store',
|
|
49
|
+
'Thumbs.db',
|
|
50
|
+
'.coverage',
|
|
51
|
+
'htmlcov',
|
|
52
|
+
'.git',
|
|
53
|
+
'.svn',
|
|
54
|
+
'.hg',
|
|
55
|
+
'test',
|
|
56
|
+
'tests',
|
|
57
|
+
'__tests__',
|
|
58
|
+
'spec',
|
|
59
|
+
'specs',
|
|
60
|
+
'tmp',
|
|
61
|
+
'temp',
|
|
62
|
+
'.tmp',
|
|
63
|
+
'.temp'
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
# Default values
|
|
67
|
+
DEFAULT_REGISTRY_URL = "https://api.comfy.org"
|
|
68
|
+
DEFAULT_GITHUB_URL = "https://github.com"
|
|
69
|
+
GITHUB_API_BASE = "https://api.github.com"
|
|
70
|
+
|
|
71
|
+
GITHUB_NODE_MAPPINGS_URL = "https://raw.githubusercontent.com/ComfyDock/ComfyDock-Registry-Data/main/data/node_mappings.json"
|
|
72
|
+
|
|
73
|
+
MAX_REGISTRY_DATA_AGE_HOURS = 24
|
|
74
|
+
|
|
75
|
+
# Prevent infinite loops for optional group removal
|
|
76
|
+
MAX_OPT_GROUP_RETRIES = 10
|
|
77
|
+
|
|
78
|
+
# PyTorch core packages
|
|
79
|
+
PYTORCH_CORE_PACKAGES = ["torch", "torchvision", "torchaudio"]
|
|
80
|
+
|
|
81
|
+
# PyTorch index base URL
|
|
82
|
+
PYTORCH_INDEX_BASE_URL = "https://download.pytorch.org/whl"
|