"""Index ComfyUI-Manager model-list.json for filename → download URL lookup.""" from __future__ import annotations import json import logging from pathlib import Path from typing import Any from comfyui_config import host_custom_nodes_dir log = logging.getLogger(__name__) MANAGER_REL_PATHS = ( "custom_nodes/ComfyUI-Manager/model-list.json", "custom_nodes/ComfyUI-Manager/node_db/new/model-list.json", ) def _manager_list_paths(data_root: Path) -> list[Path]: base = host_custom_nodes_dir(data_root).parent paths: list[Path] = [] for rel in MANAGER_REL_PATHS: path = base / rel if path.is_file(): paths.append(path) return paths def _score_entry(entry: dict[str, Any]) -> tuple[int, int]: """Prefer entries with URL and shorter save_path.""" has_url = 0 if entry.get("url") else 1 save_path = str(entry.get("save_path") or "") return (has_url, len(save_path)) def load_manager_index(data_root: Path) -> dict[str, dict[str, Any]]: """Build filename → best matching ComfyUI-Manager entry.""" index: dict[str, dict[str, Any]] = {} for list_path in _manager_list_paths(data_root): try: with list_path.open(encoding="utf-8") as fh: data = json.load(fh) except (OSError, json.JSONDecodeError) as exc: log.warning("Failed to read ComfyUI-Manager list %s: %s", list_path, exc) continue models = data.get("models") if isinstance(data, dict) else None if not isinstance(models, list): continue for entry in models: if not isinstance(entry, dict): continue filename = entry.get("filename") if not isinstance(filename, str) or not filename: continue existing = index.get(filename) if existing is None or _score_entry(entry) < _score_entry(existing): index[filename] = entry return index def lookup_manager_entry( data_root: Path, filename: str ) -> dict[str, Any] | None: return load_manager_index(data_root).get(filename)