One diagnostic node (Env Probe, utils/debug) to read a host ComfyUI runtime without terminal access — used to decide the RunComfy port strategy for ComfyUI-Human3R. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
94 lines
3.2 KiB
Python
94 lines
3.2 KiB
Python
"""Env Probe node — reports the host ComfyUI runtime environment.
|
|
|
|
Single node, no inputs, OUTPUT_NODE so it executes on its own in a one-node
|
|
workflow. It prints the report to the server console (visible in RunComfy's log
|
|
panel) AND returns it as a STRING you can wire into a Show/Preview Text node, AND
|
|
surfaces it in the node's own UI via the {"ui": {"text": ...}} channel.
|
|
"""
|
|
|
|
import sys
|
|
import platform
|
|
import importlib
|
|
|
|
|
|
def _torch_block():
|
|
lines = []
|
|
try:
|
|
import torch
|
|
lines.append(f"torch.__version__ = {torch.__version__}")
|
|
lines.append(f"torch.version.cuda = {torch.version.cuda}")
|
|
try:
|
|
lines.append(f"torch.backends.cudnn = {torch.backends.cudnn.version()}")
|
|
except Exception as e:
|
|
lines.append(f"torch.backends.cudnn = <error: {e}>")
|
|
avail = torch.cuda.is_available()
|
|
lines.append(f"torch.cuda.is_available= {avail}")
|
|
if avail:
|
|
lines.append(f"device_count = {torch.cuda.device_count()}")
|
|
for i in range(torch.cuda.device_count()):
|
|
name = torch.cuda.get_device_name(i)
|
|
cap = torch.cuda.get_device_capability(i)
|
|
lines.append(f" cuda:{i} = {name} (sm_{cap[0]}{cap[1]})")
|
|
except Exception as e:
|
|
lines.append(f"torch import FAILED: {e!r}")
|
|
return lines
|
|
|
|
|
|
def _dep_block():
|
|
# Deps relevant to the ComfyUI-Human3R port. We only check importability +
|
|
# version here; this tells us what RunComfy's Manager already resolves vs.
|
|
# what we must ship. 'curope' is the bundled compiled CUDA extension — if it
|
|
# is NOT importable, Human3R falls back to a pure-PyTorch RoPE2D.
|
|
deps = ["numpy", "smplx", "roma", "trimesh", "gsplat", "einops", "cv2"]
|
|
lines = []
|
|
for mod in deps:
|
|
try:
|
|
m = importlib.import_module(mod)
|
|
ver = getattr(m, "__version__", "?")
|
|
lines.append(f" {mod:<10} OK {ver}")
|
|
except Exception as e:
|
|
lines.append(f" {mod:<10} MISSING ({type(e).__name__})")
|
|
return lines
|
|
|
|
|
|
def build_report():
|
|
lines = []
|
|
lines.append("=" * 56)
|
|
lines.append(" ComfyUI Env Probe")
|
|
lines.append("=" * 56)
|
|
lines.append(f"sys.version = {sys.version.split(chr(10))[0]}")
|
|
lines.append(f"platform = {platform.platform()}")
|
|
lines.append("-" * 56)
|
|
lines.extend(_torch_block())
|
|
lines.append("-" * 56)
|
|
lines.append("dependency import check (for Human3R port):")
|
|
lines.extend(_dep_block())
|
|
lines.append("=" * 56)
|
|
return "\n".join(lines)
|
|
|
|
|
|
class EnvProbe:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {"required": {}}
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("report",)
|
|
FUNCTION = "run"
|
|
CATEGORY = "utils/debug"
|
|
OUTPUT_NODE = True
|
|
|
|
@classmethod
|
|
def IS_CHANGED(cls, **kwargs):
|
|
# Always re-run so the probe is never skipped by ComfyUI's result cache.
|
|
return float("nan")
|
|
|
|
def run(self):
|
|
report = build_report()
|
|
print("\n" + report + "\n", flush=True)
|
|
return {"ui": {"text": [report]}, "result": (report,)}
|
|
|
|
|
|
NODE_CLASS_MAPPINGS = {"EnvProbe": EnvProbe}
|
|
NODE_DISPLAY_NAME_MAPPINGS = {"EnvProbe": "Env Probe"}
|