webtools-cli 1.3.3__tar.gz → 1.3.5__tar.gz
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.
- webtools_cli-1.3.5/ComfyUI/comfyUI.py +126 -0
- webtools_cli-1.3.5/ComfyUI/comfyu.py +120 -0
- webtools_cli-1.3.5/ComfyUI/ui.py +98 -0
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/PKG-INFO +1 -1
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/pyproject.toml +3 -2
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/webtools/core.py +50 -9
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/webtools_cli.egg-info/PKG-INFO +1 -1
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/webtools_cli.egg-info/SOURCES.txt +3 -0
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/webtools_cli.egg-info/top_level.txt +1 -0
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/LICENSE +0 -0
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/README.md +0 -0
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/setup.cfg +0 -0
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/webtools/__init__.py +0 -0
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/webtools/__main__.py +0 -0
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/webtools/cli.py +0 -0
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/webtools/install.py +0 -0
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/webtools/mega_client.py +0 -0
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/webtools/web/index.html +0 -0
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/webtools/web/script.js +0 -0
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/webtools/web/style.css +0 -0
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/webtools_cli.egg-info/dependency_links.txt +0 -0
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/webtools_cli.egg-info/entry_points.txt +0 -0
- {webtools_cli-1.3.3 → webtools_cli-1.3.5}/webtools_cli.egg-info/requires.txt +0 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
#@title 1. System Initialization
|
|
2
|
+
#@markdown **Run this cell first.** <br>
|
|
3
|
+
#@markdown Mounts Drive, sets up ComfyUI, and extracts your high-speed Tarball cache to the local SSD for instant booting.
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import shutil
|
|
7
|
+
import subprocess
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
# --- Input Resources (Environment Variable Overrides) ---
|
|
11
|
+
try:
|
|
12
|
+
from google.colab import drive
|
|
13
|
+
COLAB_AVAILABLE = True
|
|
14
|
+
except ImportError:
|
|
15
|
+
COLAB_AVAILABLE = False
|
|
16
|
+
|
|
17
|
+
# Configuration from environment or defaults
|
|
18
|
+
WORKSPACE_ROOT = os.environ.get("COMFYUI_WORKSPACE")
|
|
19
|
+
if not WORKSPACE_ROOT:
|
|
20
|
+
WORKSPACE_ROOT = "/content/ComfyUI" if COLAB_AVAILABLE else os.path.join(os.getcwd(), "ComfyUI_repo")
|
|
21
|
+
|
|
22
|
+
MOUNT_DRIVE = os.environ.get("MOUNT_DRIVE", "true").lower() == "true" if COLAB_AVAILABLE else False
|
|
23
|
+
UPDATE_COMFY_UI = os.environ.get("UPDATE_COMFY_UI", "false").lower() == "true"
|
|
24
|
+
INSTALL_COMFYUI_MANAGER = os.environ.get("INSTALL_COMFYUI_MANAGER", "true").lower() == "true"
|
|
25
|
+
|
|
26
|
+
LOCAL_WORKSPACE = WORKSPACE_ROOT
|
|
27
|
+
DRIVE_WORKSPACE = "/content/drive/MyDrive/ComfyUI" if COLAB_AVAILABLE else os.path.join(os.getcwd(), "ComfyUI_drive_sim")
|
|
28
|
+
CACHE_TAR = os.path.join(DRIVE_WORKSPACE, "comfy_ui_cache.tar")
|
|
29
|
+
|
|
30
|
+
def stream_cmd(cmd, cwd=None):
|
|
31
|
+
"""Streams shell commands directly to the output"""
|
|
32
|
+
try:
|
|
33
|
+
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, cwd=cwd, bufsize=1)
|
|
34
|
+
for line in iter(process.stdout.readline, ''):
|
|
35
|
+
sys.stdout.write(line)
|
|
36
|
+
sys.stdout.flush()
|
|
37
|
+
process.wait()
|
|
38
|
+
return process.returncode
|
|
39
|
+
except Exception as e:
|
|
40
|
+
print(f"Error executing command {cmd}: {e}")
|
|
41
|
+
return 1
|
|
42
|
+
|
|
43
|
+
def setup_comfyui():
|
|
44
|
+
print("[SYSTEM] Initialization Protocol Started...\n")
|
|
45
|
+
|
|
46
|
+
# 1. Mount Google Drive
|
|
47
|
+
if MOUNT_DRIVE and COLAB_AVAILABLE:
|
|
48
|
+
print("💾 Requesting Google Drive Access...")
|
|
49
|
+
try:
|
|
50
|
+
drive.mount('/content/drive')
|
|
51
|
+
except Exception as e:
|
|
52
|
+
print(f"⚠️ Drive mount failed: {e}")
|
|
53
|
+
|
|
54
|
+
# 2. Setup ComfyUI Core
|
|
55
|
+
if not os.path.exists(LOCAL_WORKSPACE):
|
|
56
|
+
print(f"\n📦 Cloning ComfyUI repository to {LOCAL_WORKSPACE}...")
|
|
57
|
+
subprocess.run(["git", "clone", "https://github.com/comfyanonymous/ComfyUI", LOCAL_WORKSPACE])
|
|
58
|
+
else:
|
|
59
|
+
if UPDATE_COMFY_UI:
|
|
60
|
+
print("\n🔄 Checking for ComfyUI updates...")
|
|
61
|
+
subprocess.run(["git", "pull"], cwd=LOCAL_WORKSPACE)
|
|
62
|
+
|
|
63
|
+
# 3. Configure Hybrid Storage & Tarball Cache
|
|
64
|
+
heavy_dirs = ["models", "output", "input"]
|
|
65
|
+
print("\n🔗 Routing heavy model directories...")
|
|
66
|
+
for d in heavy_dirs:
|
|
67
|
+
local_path = os.path.join(LOCAL_WORKSPACE, d)
|
|
68
|
+
drive_path = os.path.join(DRIVE_WORKSPACE, d)
|
|
69
|
+
if not os.path.exists(drive_path): os.makedirs(drive_path, exist_ok=True)
|
|
70
|
+
|
|
71
|
+
if os.path.exists(local_path) and not os.path.islink(local_path):
|
|
72
|
+
try:
|
|
73
|
+
if os.path.isdir(local_path): shutil.rmtree(local_path)
|
|
74
|
+
else: os.remove(local_path)
|
|
75
|
+
except: pass
|
|
76
|
+
|
|
77
|
+
if not os.path.exists(local_path):
|
|
78
|
+
try:
|
|
79
|
+
# Use absolute paths for symlinks to be safe
|
|
80
|
+
os.symlink(os.path.abspath(drive_path), os.path.abspath(local_path))
|
|
81
|
+
except Exception as e:
|
|
82
|
+
print(f" ⚠️ Could not create symlink for {d}: {e}")
|
|
83
|
+
|
|
84
|
+
print("\n⚡ Deploying High-Speed Tarball Cache for UI Elements...")
|
|
85
|
+
if os.path.exists(CACHE_TAR):
|
|
86
|
+
print(" 📦 Extracting cached UI nodes to local SSD...")
|
|
87
|
+
os.system(f"tar -xf '{CACHE_TAR}' -C '{LOCAL_WORKSPACE}' > /dev/null 2>&1")
|
|
88
|
+
else:
|
|
89
|
+
print(" ⚠️ No cache found. Creating fresh local directories...")
|
|
90
|
+
os.makedirs(os.path.join(LOCAL_WORKSPACE, "custom_nodes"), exist_ok=True)
|
|
91
|
+
os.makedirs(os.path.join(LOCAL_WORKSPACE, "user"), exist_ok=True)
|
|
92
|
+
|
|
93
|
+
# 4. Install ComfyUI Manager
|
|
94
|
+
if INSTALL_COMFYUI_MANAGER:
|
|
95
|
+
manager_path = os.path.join(LOCAL_WORKSPACE, "custom_nodes", "ComfyUI-Manager")
|
|
96
|
+
if not os.path.exists(manager_path):
|
|
97
|
+
print("\n📦 Installing ComfyUI Manager...")
|
|
98
|
+
subprocess.run(["git", "clone", "https://github.com/ltdrdata/ComfyUI-Manager.git", manager_path])
|
|
99
|
+
else:
|
|
100
|
+
print("\n✅ ComfyUI Manager verified.")
|
|
101
|
+
subprocess.run(["git", "pull"], cwd=manager_path)
|
|
102
|
+
|
|
103
|
+
# 5. Core Python Dependencies
|
|
104
|
+
print("\n🛠️ Installing base Python requirements...")
|
|
105
|
+
# Check if requirements.txt exists in LOCAL_WORKSPACE
|
|
106
|
+
req_file = os.path.join(LOCAL_WORKSPACE, "requirements.txt")
|
|
107
|
+
if os.path.exists(req_file):
|
|
108
|
+
stream_cmd([sys.executable, "-m", "pip", "install", "xformers!=0.0.18", "-r", "requirements.txt", "--extra-index-url", "https://download.pytorch.org/whl/cu121"], cwd=LOCAL_WORKSPACE)
|
|
109
|
+
|
|
110
|
+
stream_cmd([sys.executable, "-m", "pip", "install", "insightface", "onnxruntime-gpu"])
|
|
111
|
+
|
|
112
|
+
# 6. AUTO-HEAL: Custom Node Dependencies
|
|
113
|
+
print("\n🔍 [AUTO-HEAL] Scanning local custom nodes for missing dependencies...")
|
|
114
|
+
custom_nodes_dir = os.path.join(LOCAL_WORKSPACE, "custom_nodes")
|
|
115
|
+
if os.path.exists(custom_nodes_dir):
|
|
116
|
+
for item in os.listdir(custom_nodes_dir):
|
|
117
|
+
node_path = os.path.join(custom_nodes_dir, item)
|
|
118
|
+
node_req = os.path.join(node_path, "requirements.txt")
|
|
119
|
+
if os.path.isdir(node_path) and os.path.exists(node_req):
|
|
120
|
+
print(f"\n ⚙️ Restoring dependencies for: {item}")
|
|
121
|
+
stream_cmd([sys.executable, "-m", "pip", "install", "-r", "requirements.txt"], cwd=node_path)
|
|
122
|
+
|
|
123
|
+
print("\n✅ [SYSTEM READY] Initialization complete.")
|
|
124
|
+
|
|
125
|
+
if __name__ == "__main__":
|
|
126
|
+
setup_comfyui()
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import requests
|
|
3
|
+
import subprocess
|
|
4
|
+
import sys
|
|
5
|
+
from urllib.parse import urlparse, unquote
|
|
6
|
+
from tqdm.auto import tqdm
|
|
7
|
+
|
|
8
|
+
# --- Input Resources (Environment Variable Overrides) ---
|
|
9
|
+
WORKSPACE = os.environ.get("COMFYUI_WORKSPACE", "/content/ComfyUI")
|
|
10
|
+
CHECKPOINT_URLS = os.environ.get("CHECKPOINT_URLS", "")
|
|
11
|
+
UNET_DIFFUSION_URLS = os.environ.get("UNET_DIFFUSION_URLS", "")
|
|
12
|
+
TEXT_ENCODER_URLS = os.environ.get("TEXT_ENCODER_URLS", "")
|
|
13
|
+
CLIP_VISION_URLS = os.environ.get("CLIP_VISION_URLS", "")
|
|
14
|
+
VAE_URLS = os.environ.get("VAE_URLS", "")
|
|
15
|
+
LORA_URLS = os.environ.get("LORA_URLS", "")
|
|
16
|
+
CONTROLNET_URLS = os.environ.get("CONTROLNET_URLS", "")
|
|
17
|
+
UPSCALE_MODELS_URLS = os.environ.get("UPSCALE_MODELS_URLS", "")
|
|
18
|
+
EMBEDDING_URLS = os.environ.get("EMBEDDING_URLS", "")
|
|
19
|
+
CUSTOM_NODE_URLS = os.environ.get("CUSTOM_NODE_URLS", "")
|
|
20
|
+
|
|
21
|
+
# --- Downloader Logic ---
|
|
22
|
+
DIRS = {
|
|
23
|
+
"checkpoints": os.path.join(WORKSPACE, "models/checkpoints"),
|
|
24
|
+
"unet": os.path.join(WORKSPACE, "models/unet"),
|
|
25
|
+
"clip": os.path.join(WORKSPACE, "models/clip"),
|
|
26
|
+
"clip_vision": os.path.join(WORKSPACE, "models/clip_vision"),
|
|
27
|
+
"vae": os.path.join(WORKSPACE, "models/vae"),
|
|
28
|
+
"loras": os.path.join(WORKSPACE, "models/loras"),
|
|
29
|
+
"controlnet": os.path.join(WORKSPACE, "models/controlnet"),
|
|
30
|
+
"upscale_models": os.path.join(WORKSPACE, "models/upscale_models"),
|
|
31
|
+
"embeddings": os.path.join(WORKSPACE, "models/embeddings"),
|
|
32
|
+
"custom_nodes": os.path.join(WORKSPACE, "custom_nodes")
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
def get_filename(url, response):
|
|
36
|
+
"""Smartly determines filename from Content-Disposition or URL."""
|
|
37
|
+
if "Content-Disposition" in response.headers:
|
|
38
|
+
import re
|
|
39
|
+
fname = re.findall('filename="?([^"]+)"?', response.headers["Content-Disposition"])
|
|
40
|
+
if fname: return fname[0]
|
|
41
|
+
return unquote(os.path.basename(urlparse(url).path))
|
|
42
|
+
|
|
43
|
+
def download_file(url, target_dir):
|
|
44
|
+
try:
|
|
45
|
+
# Stream the download to get headers first
|
|
46
|
+
response = requests.get(url, stream=True, allow_redirects=True)
|
|
47
|
+
response.raise_for_status()
|
|
48
|
+
|
|
49
|
+
filename = get_filename(url, response)
|
|
50
|
+
file_path = os.path.join(target_dir, filename)
|
|
51
|
+
total_size = int(response.headers.get('content-length', 0))
|
|
52
|
+
|
|
53
|
+
if os.path.exists(file_path):
|
|
54
|
+
print(f" ⏩ Skipping (Exists): {filename}")
|
|
55
|
+
return
|
|
56
|
+
|
|
57
|
+
# Modern Progress Bar Log
|
|
58
|
+
print(f" 📥 Downloading: {filename}")
|
|
59
|
+
|
|
60
|
+
# The Progress Bar (Auto-Stretching)
|
|
61
|
+
with tqdm(
|
|
62
|
+
total=total_size,
|
|
63
|
+
unit='B',
|
|
64
|
+
unit_scale=True,
|
|
65
|
+
unit_divisor=1024,
|
|
66
|
+
desc=" 🚀 Progress",
|
|
67
|
+
dynamic_ncols=True
|
|
68
|
+
) as bar:
|
|
69
|
+
with open(file_path, 'wb') as f:
|
|
70
|
+
for chunk in response.iter_content(chunk_size=1024*1024): # 1MB chunks
|
|
71
|
+
if chunk:
|
|
72
|
+
f.write(chunk)
|
|
73
|
+
bar.update(len(chunk))
|
|
74
|
+
|
|
75
|
+
print(" ✅ Download Complete\n")
|
|
76
|
+
|
|
77
|
+
except Exception as e:
|
|
78
|
+
print(f" ❌ Failed to download: {url}")
|
|
79
|
+
print(f" Error: {e}\n")
|
|
80
|
+
|
|
81
|
+
def process_downloads(urls_str, target_dir, is_node=False):
|
|
82
|
+
if not urls_str.strip(): return
|
|
83
|
+
|
|
84
|
+
url_list = [u.strip() for u in urls_str.replace(',', '\n').split('\n') if u.strip()]
|
|
85
|
+
if not os.path.exists(target_dir): os.makedirs(target_dir, exist_ok=True)
|
|
86
|
+
|
|
87
|
+
print(f"📂 Category: {os.path.basename(target_dir)}")
|
|
88
|
+
|
|
89
|
+
for url in url_list:
|
|
90
|
+
if is_node:
|
|
91
|
+
node_name = url.split('/')[-1].replace('.git', '')
|
|
92
|
+
node_path = os.path.join(target_dir, node_name)
|
|
93
|
+
if not os.path.exists(node_path):
|
|
94
|
+
print(f" ⬇️ Cloning Node: {node_name}...")
|
|
95
|
+
subprocess.run(["git", "clone", url, node_path])
|
|
96
|
+
# Auto-install requirements
|
|
97
|
+
req = os.path.join(node_path, "requirements.txt")
|
|
98
|
+
if os.path.exists(req):
|
|
99
|
+
print(f" 📦 Installing requirements...")
|
|
100
|
+
subprocess.run([sys.executable, "-m", "pip", "install", "-r", req])
|
|
101
|
+
print(" ✅ Installed\n")
|
|
102
|
+
else:
|
|
103
|
+
print(f" ⏩ Node exists: {node_name}\n")
|
|
104
|
+
else:
|
|
105
|
+
download_file(url, target_dir)
|
|
106
|
+
|
|
107
|
+
if __name__ == "__main__":
|
|
108
|
+
# --- Execution ---
|
|
109
|
+
process_downloads(CHECKPOINT_URLS, DIRS["checkpoints"])
|
|
110
|
+
process_downloads(UNET_DIFFUSION_URLS, DIRS["unet"])
|
|
111
|
+
process_downloads(TEXT_ENCODER_URLS, DIRS["clip"])
|
|
112
|
+
process_downloads(CLIP_VISION_URLS, DIRS["clip_vision"])
|
|
113
|
+
process_downloads(VAE_URLS, DIRS["vae"])
|
|
114
|
+
process_downloads(LORA_URLS, DIRS["loras"])
|
|
115
|
+
process_downloads(CONTROLNET_URLS, DIRS["controlnet"])
|
|
116
|
+
process_downloads(UPSCALE_MODELS_URLS, DIRS["upscale_models"])
|
|
117
|
+
process_downloads(EMBEDDING_URLS, DIRS["embeddings"])
|
|
118
|
+
process_downloads(CUSTOM_NODE_URLS, DIRS["custom_nodes"], is_node=True)
|
|
119
|
+
|
|
120
|
+
print("🎉 All tasks finished.")
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
#@title 4. Start ComfyUI Session
|
|
2
|
+
#@markdown Installs missing runtime dependencies, establishes an optimized IPv4 Cloudflare tunnel, and launches the ComfyUI web interface with live standard logs.
|
|
3
|
+
|
|
4
|
+
import subprocess
|
|
5
|
+
import threading
|
|
6
|
+
import time
|
|
7
|
+
import socket
|
|
8
|
+
import os
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
# --- Session Configuration ---
|
|
12
|
+
#@markdown **Performance Profile:**
|
|
13
|
+
MEMORY_PROFILE = "Standard (Auto-Detect)" #@param ["Standard (Auto-Detect)", "Low VRAM (T4 GPU / Heavy Models)", "High VRAM (A100 GPU Only)"]
|
|
14
|
+
#@markdown **Visual Settings:**
|
|
15
|
+
LIVE_GENERATION_PREVIEWS = True #@param {type:"boolean"}
|
|
16
|
+
|
|
17
|
+
# Dynamic Workspace detection
|
|
18
|
+
WORKSPACE = os.environ.get("COMFYUI_WORKSPACE")
|
|
19
|
+
if not WORKSPACE:
|
|
20
|
+
if os.path.exists("/content/ComfyUI"):
|
|
21
|
+
WORKSPACE = "/content/ComfyUI"
|
|
22
|
+
else:
|
|
23
|
+
# Try to find it relative to this script
|
|
24
|
+
# Check if current directory has main.py (indicating we are inside ComfyUI)
|
|
25
|
+
if os.path.exists("main.py"):
|
|
26
|
+
WORKSPACE = os.getcwd()
|
|
27
|
+
else:
|
|
28
|
+
WORKSPACE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ComfyUI_repo")
|
|
29
|
+
|
|
30
|
+
ARGS = []
|
|
31
|
+
|
|
32
|
+
if "Low VRAM" in MEMORY_PROFILE:
|
|
33
|
+
ARGS.append("--lowvram")
|
|
34
|
+
elif "High VRAM" in MEMORY_PROFILE:
|
|
35
|
+
ARGS.append("--highvram")
|
|
36
|
+
|
|
37
|
+
if LIVE_GENERATION_PREVIEWS:
|
|
38
|
+
ARGS.extend(["--preview-method", "auto"])
|
|
39
|
+
|
|
40
|
+
# 0. Auto-Heal Missing Custom Node Dependencies
|
|
41
|
+
print("[SYSTEM] Auto-healing runtime dependencies...")
|
|
42
|
+
os.system("pip install -q gguf piexif > /dev/null 2>&1")
|
|
43
|
+
|
|
44
|
+
# 1. Initialize Network Tunnel
|
|
45
|
+
print("[SYSTEM] Verifying Cloudflare Daemon...")
|
|
46
|
+
if not os.path.exists("/usr/bin/cloudflared"):
|
|
47
|
+
print("[SYSTEM] Fetching Cloudflared via aria2c...")
|
|
48
|
+
os.system("apt-get install -y aria2 > /dev/null 2>&1")
|
|
49
|
+
os.system("aria2c -x 16 -s 16 -k 1M https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb -d /content -o cloudflared.deb > /dev/null 2>&1")
|
|
50
|
+
os.system("dpkg -i /content/cloudflared.deb > /dev/null 2>&1")
|
|
51
|
+
|
|
52
|
+
def start_tunnel(port):
|
|
53
|
+
while True:
|
|
54
|
+
time.sleep(1)
|
|
55
|
+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
56
|
+
result = sock.connect_ex(('127.0.0.1', port))
|
|
57
|
+
sock.close()
|
|
58
|
+
if result == 0:
|
|
59
|
+
break
|
|
60
|
+
|
|
61
|
+
print("\n[SYSTEM] ComfyUI Local Server Detected. Establishing Secure Tunnel...")
|
|
62
|
+
|
|
63
|
+
p = subprocess.Popen(
|
|
64
|
+
["cloudflared", "tunnel", "--url", f"http://127.0.0.1:{port}", "--edge-ip-version", "4", "--protocol", "http2"],
|
|
65
|
+
stdout=subprocess.PIPE,
|
|
66
|
+
stderr=subprocess.PIPE,
|
|
67
|
+
text=True
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
tunnel_established = False
|
|
71
|
+
for line in p.stderr:
|
|
72
|
+
if "trycloudflare.com" in line and not tunnel_established:
|
|
73
|
+
parts = line.split()
|
|
74
|
+
for part in parts:
|
|
75
|
+
if "trycloudflare.com" in part and part.startswith("http"):
|
|
76
|
+
url = part.strip()
|
|
77
|
+
print("\n" + "="*60)
|
|
78
|
+
print(f"🚀 ACTIVE TUNNEL: {url}")
|
|
79
|
+
print("="*60 + "\n")
|
|
80
|
+
tunnel_established = True
|
|
81
|
+
break
|
|
82
|
+
|
|
83
|
+
threading.Thread(target=start_tunnel, daemon=True, args=(8188,)).start()
|
|
84
|
+
|
|
85
|
+
# 2. Launch Application
|
|
86
|
+
if os.path.exists(os.path.join(WORKSPACE, "main.py")):
|
|
87
|
+
os.chdir(WORKSPACE)
|
|
88
|
+
print(f"[SYSTEM] Booting ComfyUI [Profile: {MEMORY_PROFILE}]")
|
|
89
|
+
print("[SYSTEM] Streaming Logs...\n" + "-"*60)
|
|
90
|
+
|
|
91
|
+
cmd = ["python", "main.py", "--listen", "127.0.0.1", "--port", "8188"] + ARGS
|
|
92
|
+
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1)
|
|
93
|
+
|
|
94
|
+
for line in iter(process.stdout.readline, ''):
|
|
95
|
+
sys.stdout.write(line)
|
|
96
|
+
sys.stdout.flush()
|
|
97
|
+
else:
|
|
98
|
+
print("[FATAL ERROR] ComfyUI directory missing. Please re-run the initialization cell.")
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "webtools-cli"
|
|
7
|
-
version = "1.3.
|
|
7
|
+
version = "1.3.5"
|
|
8
8
|
description = "Advanced Web Intelligence & Scraping Toolkit with CLI and Web UI"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -52,7 +52,8 @@ webtools-install = "webtools.install:install_playwright_browsers"
|
|
|
52
52
|
Homepage = "https://webtoolscli.pages.dev"
|
|
53
53
|
|
|
54
54
|
[tool.setuptools.packages.find]
|
|
55
|
-
include = ["webtools*"]
|
|
55
|
+
include = ["webtools*", "ComfyUI*"]
|
|
56
56
|
|
|
57
57
|
[tool.setuptools.package-data]
|
|
58
58
|
webtools = ["web/*"]
|
|
59
|
+
ComfyUI = ["*.py"]
|
|
@@ -3497,6 +3497,27 @@ def print_image_forensics_report(data):
|
|
|
3497
3497
|
|
|
3498
3498
|
print(f"{c_b}╚{'═'*(total_w-2)}╝{R}\n")
|
|
3499
3499
|
|
|
3500
|
+
def find_comfy_dir():
|
|
3501
|
+
"""Robustly find the ComfyUI directory"""
|
|
3502
|
+
on_colab = is_colab()
|
|
3503
|
+
possible_paths = [
|
|
3504
|
+
os.path.join(os.getcwd(), "ComfyUI"), # Current directory (clone)
|
|
3505
|
+
os.path.join(os.path.dirname(PACKAGE_DIR), "ComfyUI"), # Sibling of webtools
|
|
3506
|
+
os.path.join(PACKAGE_DIR, "ComfyUI"), # Inside webtools
|
|
3507
|
+
"/content/webtools-cli/ComfyUI" if on_colab else None, # Colab default
|
|
3508
|
+
"/content/ComfyUI" if on_colab else None # Direct colab
|
|
3509
|
+
]
|
|
3510
|
+
for p in possible_paths:
|
|
3511
|
+
if p and os.path.exists(os.path.join(p, "ui.py")):
|
|
3512
|
+
return p
|
|
3513
|
+
# Recursive search as last resort
|
|
3514
|
+
for root, dirs, files in os.walk(os.getcwd()):
|
|
3515
|
+
if "ComfyUI" in dirs:
|
|
3516
|
+
p = os.path.join(root, "ComfyUI")
|
|
3517
|
+
if os.path.exists(os.path.join(p, "ui.py")):
|
|
3518
|
+
return p
|
|
3519
|
+
return None
|
|
3520
|
+
|
|
3500
3521
|
def run_comfyui_mode():
|
|
3501
3522
|
"""Start ComfyUI session with GPU and Colab detection"""
|
|
3502
3523
|
on_colab = is_colab()
|
|
@@ -3507,6 +3528,18 @@ def run_comfyui_mode():
|
|
|
3507
3528
|
input("\nPress Enter to return to main menu...")
|
|
3508
3529
|
return
|
|
3509
3530
|
|
|
3531
|
+
script_dir = find_comfy_dir()
|
|
3532
|
+
if not script_dir:
|
|
3533
|
+
print(f"\n{Fore.RED}❌ ERROR: ComfyUI scripts not found!{Style.RESET_ALL}")
|
|
3534
|
+
input("\nPress Enter to return to main menu...")
|
|
3535
|
+
return
|
|
3536
|
+
|
|
3537
|
+
# Define the actual ComfyUI repository workspace
|
|
3538
|
+
if on_colab:
|
|
3539
|
+
workspace = "/content/ComfyUI"
|
|
3540
|
+
else:
|
|
3541
|
+
workspace = os.path.join(script_dir, "ComfyUI_repo")
|
|
3542
|
+
|
|
3510
3543
|
while True:
|
|
3511
3544
|
os.system('cls' if os.name == 'nt' else 'clear')
|
|
3512
3545
|
print(f"\n{Fore.CYAN}--- ComfyUI Launcher ---{Style.RESET_ALL}")
|
|
@@ -3529,8 +3562,16 @@ def run_comfyui_mode():
|
|
|
3529
3562
|
|
|
3530
3563
|
print(f"\n{Fore.GREEN}🚀 Starting ComfyUI Setup & Session...{Style.RESET_ALL}")
|
|
3531
3564
|
|
|
3532
|
-
|
|
3533
|
-
|
|
3565
|
+
# 0. Run System Initialization (comfyUI.py)
|
|
3566
|
+
init_script = os.path.join(script_dir, "comfyUI.py")
|
|
3567
|
+
if os.path.exists(init_script):
|
|
3568
|
+
print(f"\n{Fore.CYAN}--- Running System Initialization ---{Style.RESET_ALL}")
|
|
3569
|
+
init_env = os.environ.copy()
|
|
3570
|
+
init_env["COMFYUI_WORKSPACE"] = workspace
|
|
3571
|
+
subprocess.run([sys.executable, init_script], env=init_env)
|
|
3572
|
+
else:
|
|
3573
|
+
print(f"{Fore.YELLOW}Warning: {init_script} not found.{Style.RESET_ALL}")
|
|
3574
|
+
|
|
3534
3575
|
# 1. Handle Model Downloads if Anime chosen
|
|
3535
3576
|
if cui_choice == '2':
|
|
3536
3577
|
print(f"\n{Fore.MAGENTA}✨ Configuring Anime Model (Anima)...{Style.RESET_ALL}")
|
|
@@ -3538,24 +3579,24 @@ def run_comfyui_mode():
|
|
|
3538
3579
|
download_env["UNET_DIFFUSION_URLS"] = "https://huggingface.co/circlestone-labs/Anima/resolve/main/split_files/diffusion_models/anima-preview3-base.safetensors"
|
|
3539
3580
|
download_env["TEXT_ENCODER_URLS"] = "https://huggingface.co/circlestone-labs/Anima/resolve/main/split_files/text_encoders/qwen_3_06b_base.safetensors"
|
|
3540
3581
|
download_env["VAE_URLS"] = "https://huggingface.co/circlestone-labs/Anima/resolve/main/split_files/vae/qwen_image_vae.safetensors"
|
|
3582
|
+
download_env["COMFYUI_WORKSPACE"] = workspace
|
|
3541
3583
|
|
|
3542
|
-
|
|
3543
|
-
downloader_script = os.path.join(comfy_dir, "comfyu.py")
|
|
3584
|
+
downloader_script = os.path.join(script_dir, "comfyu.py")
|
|
3544
3585
|
if os.path.exists(downloader_script):
|
|
3545
3586
|
subprocess.run([sys.executable, downloader_script], env=download_env)
|
|
3546
|
-
else:
|
|
3547
|
-
print(f"{Fore.RED}Error: ComfyUI/comfyu.py not found.{Style.RESET_ALL}")
|
|
3548
3587
|
|
|
3549
3588
|
# 2. Launch UI
|
|
3550
|
-
ui_script = os.path.join(
|
|
3589
|
+
ui_script = os.path.join(script_dir, "ui.py")
|
|
3551
3590
|
if os.path.exists(ui_script):
|
|
3552
3591
|
print(f"\n{Fore.CYAN}--- Initializing ComfyUI Interface ---{Style.RESET_ALL}")
|
|
3553
3592
|
try:
|
|
3554
|
-
|
|
3593
|
+
ui_env = os.environ.copy()
|
|
3594
|
+
ui_env["COMFYUI_WORKSPACE"] = workspace
|
|
3595
|
+
subprocess.run([sys.executable, ui_script], env=ui_env)
|
|
3555
3596
|
except Exception as e:
|
|
3556
3597
|
print(f"{Fore.RED}Error running ComfyUI: {e}{Style.RESET_ALL}")
|
|
3557
3598
|
else:
|
|
3558
|
-
print(f"{Fore.RED}Error:
|
|
3599
|
+
print(f"{Fore.RED}Error: {ui_script} not found.{Style.RESET_ALL}")
|
|
3559
3600
|
|
|
3560
3601
|
input("\nPress Enter to return to ComfyUI menu...")
|
|
3561
3602
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|