Enhanced backend (nodes.py, __init__.py): Added robust error handling for loading resolutions.json and aspect_ratios.json with safe defaults. Implemented per-file error handling when loading individual model configurations to prevent one failure from blocking others. Added data structure validation for model files. Introduced a comprehensive fallback data structure in __init__.py to ensure the node initializes and functions even if all data loading fails. Strengthened frontend (js/optimal_resolution.js): Added HTTP status check and data structure validation for the /optimal_resolution/models API response. Implemented null/undefined checks (?.) and explicit validation for all widget lookups and critical data properties. Made widget callbacks safer by verifying the original callback is a function before calling it. Added a minimal fallback data structure in the fetch error handler to prevent UI crashes.
84 lines
2.7 KiB
Python
84 lines
2.7 KiB
Python
from .nodes import OptimalResolutionNode, load_models_data, NODE_DIR
|
|
from .nodes import ComfyExtension, io
|
|
from server import PromptServer
|
|
import json
|
|
import os
|
|
import aiohttp
|
|
|
|
|
|
WEB_DIRECTORY = "./js"
|
|
|
|
# Load data immediately at module import time with error handling
|
|
try:
|
|
OptimalResolutionNode.models_data = load_models_data()
|
|
if not OptimalResolutionNode.models_data:
|
|
raise ValueError("Loaded data is empty")
|
|
except Exception as e:
|
|
print(f"[OptimalResolution] Critical error during initialization: {e}. Using fallback data.")
|
|
# Fallback to minimal viable data structure
|
|
OptimalResolutionNode.models_data = {
|
|
"model_types": {"Image": ["Fallback Model"], "Video": []},
|
|
"models_data": {
|
|
"Fallback Model": {
|
|
"base_resolution": 1024,
|
|
"multiple_of": 16,
|
|
"resolution_options": {
|
|
"values": ["Standard"],
|
|
"default": "Standard"
|
|
}
|
|
},
|
|
"default": {
|
|
"base_resolution": 1024,
|
|
"multiple_of": 16
|
|
}
|
|
},
|
|
"resolutions": {},
|
|
"aspect_ratios": {}
|
|
}
|
|
|
|
class OptimalResolutionExtension(ComfyExtension):
|
|
async def get_node_list(self) -> list[type[io.ComfyNode]]:
|
|
return [OptimalResolutionNode]
|
|
|
|
async def comfy_entrypoint() -> ComfyExtension:
|
|
return OptimalResolutionExtension()
|
|
|
|
# Setup API Routes
|
|
prompt_server = PromptServer.instance
|
|
|
|
@prompt_server.routes.get("/optimal_resolution/models")
|
|
async def get_models_data(request):
|
|
"""Returns the configuration JSON to the frontend."""
|
|
data = OptimalResolutionNode.models_data
|
|
if not data:
|
|
data = load_models_data()
|
|
return aiohttp.web.json_response(data, status=200)
|
|
|
|
@prompt_server.routes.post("/optimal_resolution/calculate")
|
|
async def calculate_resolution_api(request):
|
|
"""Calculates resolution without executing the workflow."""
|
|
try:
|
|
body = await request.json()
|
|
model_type = body.get("model_type", "Image")
|
|
model = body.get("model", "Flux 1")
|
|
aspect_ratio = body.get("aspect_ratio", "1:1")
|
|
resolution = body.get("resolution", "Standard")
|
|
|
|
data = OptimalResolutionNode.models_data
|
|
if not data:
|
|
data = load_models_data()
|
|
|
|
w, h, text = OptimalResolutionNode.calculate_resolution_logic(
|
|
model_type, model, aspect_ratio, resolution, data
|
|
)
|
|
|
|
return aiohttp.web.json_response({
|
|
"width": w,
|
|
"height": h,
|
|
"resolution_text": text
|
|
}, status=200)
|
|
except Exception as e:
|
|
print(f"[OptimalResolution] API Error: {e}")
|
|
return aiohttp.web.json_response({"error": str(e)}, status=500)
|
|
|
|
__all__ = ['WEB_DIRECTORY'] |