File size: 8,350 Bytes
6bcb2c3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d1dc2f7
 
 
 
6bcb2c3
d1dc2f7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6bcb2c3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2b442eb
6bcb2c3
2b442eb
68fa46a
 
 
 
 
 
 
 
 
 
 
 
55e1756
d1dc2f7
4734897
e327a4a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
eb20296
bec4723
eb20296
 
 
 
d1dc2f7
6fdb441
2b442eb
6bcb2c3
 
 
 
 
 
 
 
2b442eb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
import os
import sys
import shutil

from core.settings import *

def move_and_overwrite(src, dst):
    if os.path.isdir(src):
        if os.path.exists(dst):
            shutil.rmtree(dst)
        shutil.move(src, dst)
    elif os.path.isfile(src):
        if os.path.exists(dst):
            os.remove(dst)
        shutil.move(src, dst)

def initialize_comfyui():
    APP_DIR = sys.path[0]
    COMFYUI_TEMP_DIR = "ComfyUI_temp"

    print("--- Cloning ComfyUI Repository ---")
    if not os.path.exists(COMFYUI_TEMP_DIR):
        os.system(f"git clone https://github.com/comfy-Org/ComfyUI {COMFYUI_TEMP_DIR}")
        print("✅ ComfyUI repository cloned.")
    else:
        print("✅ ComfyUI repository already exists.")

    print(f"--- Merging ComfyUI from '{COMFYUI_TEMP_DIR}' to '{APP_DIR}' ---")
    for item in os.listdir(COMFYUI_TEMP_DIR):
        src_path = os.path.join(COMFYUI_TEMP_DIR, item)
        dst_path = os.path.join(APP_DIR, item)
        if item == '.git':
            continue
        move_and_overwrite(src_path, dst_path)
    
    try:
        shutil.rmtree(COMFYUI_TEMP_DIR)
        print("✅ ComfyUI merged and temporary directory removed.")
    except OSError as e:
        print(f"⚠️ Could not remove temporary directory '{COMFYUI_TEMP_DIR}': {e}")

    print("--- Cloning third-party extensions for ComfyUI ---")

    # 1. ComfyUI_IPAdapter_plus
    ipadapter_plus_path = os.path.join(APP_DIR, "custom_nodes", "ComfyUI_IPAdapter_plus")
    if not os.path.exists(ipadapter_plus_path):
        os.system(f"git clone https://github.com/cubiq/ComfyUI_IPAdapter_plus.git {ipadapter_plus_path}")
        print("✅ ComfyUI_IPAdapter_plus extension cloned.")
    else:
        print("✅ ComfyUI_IPAdapter_plus extension already exists.")

    # 2. ComfyUI-InstantX-IPAdapter-SD3
    ipadapter_plus_path = os.path.join(APP_DIR, "custom_nodes", "ComfyUI-InstantX-IPAdapter-SD3")
    if not os.path.exists(ipadapter_plus_path):
        os.system(f"git clone https://github.com/Slickytail/ComfyUI-InstantX-IPAdapter-SD3.git {ipadapter_plus_path}")
        print("✅ ComfyUI-InstantX-IPAdapter-SD3 extension cloned.")
    else:
        print("✅ ComfyUI-InstantX-IPAdapter-SD3 extension already exists.")

    # 3. ComfyUI-IPAdapter-Flux
    ipadapter_flux_path = os.path.join(APP_DIR, "custom_nodes", "ComfyUI-IPAdapter-Flux")
    if not os.path.exists(ipadapter_flux_path):
        os.system(f"git clone https://github.com/Shakker-Labs/ComfyUI-IPAdapter-Flux.git {ipadapter_flux_path}")
        print("✅ ComfyUI-IPAdapter-Flux extension cloned.")
    else:
        print("✅ ComfyUI-IPAdapter-Flux extension already exists.")

    # 4. ComfyUI-Newbie-Nodes
    newbie_nodes_path = os.path.join(APP_DIR, "custom_nodes", "ComfyUI-Newbie-Nodes")
    if not os.path.exists(newbie_nodes_path):
        os.system(f"git clone https://github.com/NewBieAI-Lab/ComfyUI-Newbie-Nodes.git {newbie_nodes_path}")
        print("✅ ComfyUI-Newbie-Nodes extension cloned.")
    else:
        print("✅ ComfyUI-Newbie-Nodes extension already exists.")

    # 5. ComfyUI-Anima-LLLite
    anima_controlnet_lllite_nodes_path = os.path.join(APP_DIR, "custom_nodes", "ComfyUI-Anima-LLLite")
    if not os.path.exists(anima_controlnet_lllite_nodes_path):
        os.system(f"git clone https://github.com/kohya-ss/ComfyUI-Anima-LLLite.git {anima_controlnet_lllite_nodes_path}")
        print("✅ ComfyUI-Anima-LLLite extension cloned.")
    else:
        print("✅ ComfyUI-Anima-LLLite extension already exists.")

    print(f"✅ Current working directory is: {os.getcwd()}")
    
    # Ensure torch treats CUDA as unavailable on CPU‑only environment.
    import torch
    torch.cuda.is_available = lambda: False
    # Additional CUDA stubs to prevent calls like torch.cuda.get_device_properties
    class _DummyDeviceProps:
        def __init__(self):
            self.major = 0
            self.minor = 0
            self.total_memory = 0
    def _dummy_get_device_properties(device):
        return _DummyDeviceProps()
    torch.cuda.get_device_properties = _dummy_get_device_properties
    torch.cuda.device_count = lambda: 0
    torch.cuda.current_device = lambda: 0
    torch.cuda.get_device_name = lambda device: "cpu"


    # Apply patch to the external ComfyUI model_management before import.
    external_model_mgmt_path = os.path.join(APP_DIR, "comfy", "model_management.py")
    if os.path.exists(external_model_mgmt_path):
        try:
            with open(external_model_mgmt_path, "r", encoding="utf-8") as f:
                content = f.read()
            start = content.find("def get_torch_device():")
            if start != -1:
                # Find the end of the function (next def or end of file)
                end = content.find("\ndef ", start + 1)
                if end == -1:
                    end = len(content)
                new_func = """def get_torch_device():
    \"\"\"Return appropriate torch device, falling back to CPU when needed.\"\"\"
    global directml_enabled, cpu_state
    if directml_enabled:
        return directml_device
    if cpu_state == CPUState.MPS:
        return torch.device(\"mps\")
    if cpu_state == CPUState.CPU:
        return torch.device(\"cpu\")
    if is_intel_xpu():
        return torch.device(\"xpu\", torch.xpu.current_device())
    if is_ascend_npu():
        return torch.device(\"npu\", torch.npu.current_device())
    if is_mlu():
        return torch.device(\"mlu\", torch.mlu.current_device())
    if torch.cuda.is_available():
        return torch.device(torch.cuda.current_device())
    return torch.device(\"cpu\")
"""
                patched_content = content[:start] + new_func + content[end:]
                with open(external_model_mgmt_path, "w", encoding="utf-8") as f:
                    f.write(patched_content)
        except Exception as e:
            print(f"⚠️ Failed to patch external model_management: {e}")

    import comfy.model_management as model_mgmt
    # Patch get_torch_device to enforce CPU fallback.
    def _cpu_fallback_get_torch_device():
        """Return appropriate torch device, falling back to CPU when needed.

        This patch replaces the original implementation that assumed a CUDA GPU
        and raised a RuntimeError on CPU‑only systems. It respects the existing
        ``directml_enabled`` and ``cpu_state`` flags, and falls back to CPU when
        no GPU backend is available.
        """
        # DirectML path – unchanged.
        if model_mgmt.directml_enabled:
            return model_mgmt.directml_device
        # Apple Silicon / MPS backend.
        if model_mgmt.cpu_state == model_mgmt.CPUState.MPS:
            return torch.device("mps")
        # Explicit CPU request.
        if model_mgmt.cpu_state == model_mgmt.CPUState.CPU:
            return torch.device("cpu")
        # Intel XPU, Ascend NPU, MLU – retain original handling.
        if model_mgmt.is_intel_xpu():
            return torch.device("xpu", torch.xpu.current_device())
        if model_mgmt.is_ascend_npu():
            return torch.device("npu", torch.npu.current_device())
        if model_mgmt.is_mlu():
            return torch.device("mlu", torch.mlu.current_device())
        # CUDA – use if available (will be False due to monkey‑patch).
        if torch.cuda.is_available():
            return torch.device(torch.cuda.current_device())
        # Default to CPU.
        return torch.device("cpu")
    model_mgmt.get_torch_device = _cpu_fallback_get_torch_device
    import importlib
    importlib.reload(model_mgmt)
    # Override should_use_bf16 to avoid any CUDA device property queries on CPU‑only systems.
    def _safe_should_use_bf16(device, model_params=None, manual_cast=False):
        """Return False unconditionally – no BF16 support on CPU‑only environment."""
        return False
    model_mgmt.should_use_bf16 = _safe_should_use_bf16

 
    print("--- Environment Ready ---")
    
    print("✅ ComfyUI initialized with default attention mechanism.")

    for dir_path in CATEGORY_TO_DIR_MAP.values():
        os.makedirs(os.path.join(APP_DIR, dir_path), exist_ok=True)
    
    os.makedirs(os.path.join(APP_DIR, INPUT_DIR), exist_ok=True)
    os.makedirs(os.path.join(APP_DIR, OUTPUT_DIR), exist_ok=True)
    
    print("✅ All required model directories are present.")