mirror of
https://github.com/HuangYuChuh/ComfyUI_Skills_OpenClaw.git
synced 2026-07-29 19:17:38 +00:00
127 lines
3.8 KiB
Python
127 lines
3.8 KiB
Python
#!/usr/bin/env python3
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
import urllib.error
|
|
import urllib.request
|
|
import webbrowser
|
|
from pathlib import Path
|
|
|
|
SCRIPT_DIR = Path(__file__).resolve().parent
|
|
ROOT_DIR = SCRIPT_DIR.parent
|
|
|
|
if str(SCRIPT_DIR) not in sys.path:
|
|
sys.path.insert(0, str(SCRIPT_DIR))
|
|
if str(ROOT_DIR / "scripts") not in sys.path:
|
|
sys.path.insert(0, str(ROOT_DIR / "scripts"))
|
|
|
|
from settings import DEFAULT_HOST, DEFAULT_PORT # noqa: E402
|
|
|
|
|
|
def build_ui_url() -> str:
|
|
host = DEFAULT_HOST if DEFAULT_HOST not in {"0.0.0.0", "::"} else "127.0.0.1"
|
|
return f"http://{host}:{DEFAULT_PORT}"
|
|
|
|
|
|
def is_ui_ready(url: str, timeout: float = 1.0) -> bool:
|
|
try:
|
|
with urllib.request.urlopen(url, timeout=timeout) as response:
|
|
return 200 <= response.status < 500
|
|
except (urllib.error.URLError, TimeoutError, ValueError):
|
|
return False
|
|
|
|
|
|
def wait_until_ready(url: str, timeout_seconds: float) -> bool:
|
|
deadline = time.time() + timeout_seconds
|
|
while time.time() < deadline:
|
|
if is_ui_ready(url):
|
|
return True
|
|
time.sleep(0.5)
|
|
return False
|
|
|
|
|
|
def start_ui_process(python_bin: str) -> tuple[subprocess.Popen[bytes], Path]:
|
|
log_path = SCRIPT_DIR / "ui.log"
|
|
log_handle = log_path.open("ab")
|
|
launcher = SCRIPT_DIR / "run_ui.sh"
|
|
kwargs: dict[str, object] = {
|
|
"cwd": str(ROOT_DIR),
|
|
"stdin": subprocess.DEVNULL,
|
|
"stdout": log_handle,
|
|
"stderr": subprocess.STDOUT,
|
|
"close_fds": os.name != "nt",
|
|
}
|
|
|
|
# 使用独立会话启动,避免 Agent 进程退出时把 UI 一起带走。
|
|
if os.name == "nt":
|
|
detached = getattr(subprocess, "DETACHED_PROCESS", 0)
|
|
new_group = getattr(subprocess, "CREATE_NEW_PROCESS_GROUP", 0)
|
|
kwargs["creationflags"] = detached | new_group
|
|
else:
|
|
kwargs["start_new_session"] = True
|
|
|
|
if os.name == "nt":
|
|
process = subprocess.Popen([python_bin, str(SCRIPT_DIR / "app.py")], **kwargs)
|
|
else:
|
|
env = os.environ.copy()
|
|
env.setdefault("PYTHON_BIN", python_bin)
|
|
kwargs["env"] = env
|
|
process = subprocess.Popen([str(launcher)], **kwargs)
|
|
return process, log_path
|
|
|
|
|
|
def open_browser(url: str) -> bool:
|
|
try:
|
|
return bool(webbrowser.open(url, new=2, autoraise=True))
|
|
except webbrowser.Error:
|
|
return False
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description="Start the local OpenClaw ComfyUI UI and open it in a browser.")
|
|
parser.add_argument("--no-browser", action="store_true", help="Start the UI without opening a browser window.")
|
|
parser.add_argument("--timeout", type=float, default=20.0, help="Seconds to wait for the UI to become ready.")
|
|
args = parser.parse_args()
|
|
|
|
url = build_ui_url()
|
|
python_bin = sys.executable or "python3"
|
|
|
|
result = {
|
|
"status": "success",
|
|
"url": url,
|
|
"already_running": False,
|
|
"browser_opened": False,
|
|
"log_path": str(SCRIPT_DIR / "ui.log"),
|
|
}
|
|
|
|
if is_ui_ready(url):
|
|
result["already_running"] = True
|
|
else:
|
|
process, log_path = start_ui_process(python_bin)
|
|
result["log_path"] = str(log_path)
|
|
if not wait_until_ready(url, args.timeout):
|
|
print(json.dumps({
|
|
"status": "error",
|
|
"url": url,
|
|
"message": "UI did not become ready in time.",
|
|
"log_path": str(log_path),
|
|
"pid": process.pid,
|
|
}, ensure_ascii=False))
|
|
return 1
|
|
result["pid"] = process.pid
|
|
|
|
if not args.no_browser:
|
|
result["browser_opened"] = open_browser(url)
|
|
|
|
print(json.dumps(result, ensure_ascii=False))
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|