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.
Files changed (93) hide show
  1. comfygit_core/analyzers/custom_node_scanner.py +109 -0
  2. comfygit_core/analyzers/git_change_parser.py +156 -0
  3. comfygit_core/analyzers/model_scanner.py +318 -0
  4. comfygit_core/analyzers/node_classifier.py +58 -0
  5. comfygit_core/analyzers/node_git_analyzer.py +77 -0
  6. comfygit_core/analyzers/status_scanner.py +362 -0
  7. comfygit_core/analyzers/workflow_dependency_parser.py +143 -0
  8. comfygit_core/caching/__init__.py +16 -0
  9. comfygit_core/caching/api_cache.py +210 -0
  10. comfygit_core/caching/base.py +212 -0
  11. comfygit_core/caching/comfyui_cache.py +100 -0
  12. comfygit_core/caching/custom_node_cache.py +320 -0
  13. comfygit_core/caching/workflow_cache.py +797 -0
  14. comfygit_core/clients/__init__.py +4 -0
  15. comfygit_core/clients/civitai_client.py +412 -0
  16. comfygit_core/clients/github_client.py +349 -0
  17. comfygit_core/clients/registry_client.py +230 -0
  18. comfygit_core/configs/comfyui_builtin_nodes.py +1614 -0
  19. comfygit_core/configs/comfyui_models.py +62 -0
  20. comfygit_core/configs/model_config.py +151 -0
  21. comfygit_core/constants.py +82 -0
  22. comfygit_core/core/environment.py +1635 -0
  23. comfygit_core/core/workspace.py +898 -0
  24. comfygit_core/factories/environment_factory.py +419 -0
  25. comfygit_core/factories/uv_factory.py +61 -0
  26. comfygit_core/factories/workspace_factory.py +109 -0
  27. comfygit_core/infrastructure/sqlite_manager.py +156 -0
  28. comfygit_core/integrations/__init__.py +7 -0
  29. comfygit_core/integrations/uv_command.py +318 -0
  30. comfygit_core/logging/logging_config.py +15 -0
  31. comfygit_core/managers/environment_git_orchestrator.py +316 -0
  32. comfygit_core/managers/environment_model_manager.py +296 -0
  33. comfygit_core/managers/export_import_manager.py +116 -0
  34. comfygit_core/managers/git_manager.py +667 -0
  35. comfygit_core/managers/model_download_manager.py +252 -0
  36. comfygit_core/managers/model_symlink_manager.py +166 -0
  37. comfygit_core/managers/node_manager.py +1378 -0
  38. comfygit_core/managers/pyproject_manager.py +1321 -0
  39. comfygit_core/managers/user_content_symlink_manager.py +436 -0
  40. comfygit_core/managers/uv_project_manager.py +569 -0
  41. comfygit_core/managers/workflow_manager.py +1944 -0
  42. comfygit_core/models/civitai.py +432 -0
  43. comfygit_core/models/commit.py +18 -0
  44. comfygit_core/models/environment.py +293 -0
  45. comfygit_core/models/exceptions.py +378 -0
  46. comfygit_core/models/manifest.py +132 -0
  47. comfygit_core/models/node_mapping.py +201 -0
  48. comfygit_core/models/protocols.py +248 -0
  49. comfygit_core/models/registry.py +63 -0
  50. comfygit_core/models/shared.py +356 -0
  51. comfygit_core/models/sync.py +42 -0
  52. comfygit_core/models/system.py +204 -0
  53. comfygit_core/models/workflow.py +914 -0
  54. comfygit_core/models/workspace_config.py +71 -0
  55. comfygit_core/py.typed +0 -0
  56. comfygit_core/repositories/migrate_paths.py +49 -0
  57. comfygit_core/repositories/model_repository.py +958 -0
  58. comfygit_core/repositories/node_mappings_repository.py +246 -0
  59. comfygit_core/repositories/workflow_repository.py +57 -0
  60. comfygit_core/repositories/workspace_config_repository.py +121 -0
  61. comfygit_core/resolvers/global_node_resolver.py +459 -0
  62. comfygit_core/resolvers/model_resolver.py +250 -0
  63. comfygit_core/services/import_analyzer.py +218 -0
  64. comfygit_core/services/model_downloader.py +422 -0
  65. comfygit_core/services/node_lookup_service.py +251 -0
  66. comfygit_core/services/registry_data_manager.py +161 -0
  67. comfygit_core/strategies/__init__.py +4 -0
  68. comfygit_core/strategies/auto.py +72 -0
  69. comfygit_core/strategies/confirmation.py +69 -0
  70. comfygit_core/utils/comfyui_ops.py +125 -0
  71. comfygit_core/utils/common.py +164 -0
  72. comfygit_core/utils/conflict_parser.py +232 -0
  73. comfygit_core/utils/dependency_parser.py +231 -0
  74. comfygit_core/utils/download.py +216 -0
  75. comfygit_core/utils/environment_cleanup.py +111 -0
  76. comfygit_core/utils/filesystem.py +178 -0
  77. comfygit_core/utils/git.py +1184 -0
  78. comfygit_core/utils/input_signature.py +145 -0
  79. comfygit_core/utils/model_categories.py +52 -0
  80. comfygit_core/utils/pytorch.py +71 -0
  81. comfygit_core/utils/requirements.py +211 -0
  82. comfygit_core/utils/retry.py +242 -0
  83. comfygit_core/utils/symlink_utils.py +119 -0
  84. comfygit_core/utils/system_detector.py +258 -0
  85. comfygit_core/utils/uuid.py +28 -0
  86. comfygit_core/utils/uv_error_handler.py +158 -0
  87. comfygit_core/utils/version.py +73 -0
  88. comfygit_core/utils/workflow_hash.py +90 -0
  89. comfygit_core/validation/resolution_tester.py +297 -0
  90. comfygit_core-0.2.0.dist-info/METADATA +939 -0
  91. comfygit_core-0.2.0.dist-info/RECORD +93 -0
  92. comfygit_core-0.2.0.dist-info/WHEEL +4 -0
  93. 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"