Compare commits

..
3 changed files with 60 additions and 38 deletions
+4 -4
View File
@@ -4,6 +4,7 @@ import numpy as np
from PIL import Image
from PIL.PngImagePlugin import PngInfo
import folder_paths
from comfy.cli_args import args
class ComfyDeployOutputImage:
@@ -33,7 +34,6 @@ class ComfyDeployOutputImage:
"STRING",
{"multiline": False, "default": "output_images"},
),
"remove_metadata": ("BOOLEAN", {"default": True}),
},
"hidden": {"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"},
}
@@ -54,7 +54,6 @@ class ComfyDeployOutputImage:
output_id="output_images",
prompt=None,
extra_pnginfo=None,
remove_metadata=True,
):
filename_prefix += self.prefix_append
full_output_folder, filename, counter, subfolder, filename_prefix = (
@@ -66,8 +65,9 @@ class ComfyDeployOutputImage:
for batch_number, image in enumerate(images):
i = 255.0 * image.cpu().numpy()
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
metadata = PngInfo()
if not remove_metadata:
metadata = None
if not args.disable_metadata:
metadata = PngInfo()
if prompt is not None:
metadata.add_text("prompt", json.dumps(prompt))
if extra_pnginfo is not None:
+55 -33
View File
@@ -1,8 +1,5 @@
from io import BytesIO
from pprint import pprint
from aiohttp import web
import os
import requests
import folder_paths
import json
import server
@@ -13,34 +10,24 @@ import random
import traceback
import uuid
import asyncio
import logging
from urllib.parse import quote
import inspect
from urllib.parse import quote, urlencode
import threading
import hashlib
import aiohttp
from aiohttp import ClientSession, web
from aiohttp import web, ClientSession, ClientError, ClientTimeout
import aiofiles
from typing import Dict, List, Union, Any, Optional
from PIL import Image
from typing import Dict, Any
import copy
import struct
from aiohttp import web, ClientSession, ClientError, ClientTimeout, ClientResponseError
import atexit
from model_management import get_torch_device
import torch
import psutil
from collections import OrderedDict
import io
from urllib.parse import urlencode
# Global session
client_session = None
# def create_client_session():
# global client_session
# if client_session is None:
# client_session = aiohttp.ClientSession()
async def ensure_client_session():
global client_session
@@ -82,8 +69,6 @@ retry_delay_multiplier = float(os.environ.get("RETRY_DELAY_MULTIPLIER", "2"))
print(f"max_retries: {max_retries}, retry_delay_multiplier: {retry_delay_multiplier}")
import time
async def async_request_with_retry(
method, url, disable_timeout=False, token=None, **kwargs
@@ -334,9 +319,28 @@ async def post_prompt(json_data):
extra_data["client_id"] = json_data["client_id"]
if valid[0]:
outputs_to_execute = valid[2]
prompt_server.prompt_queue.put(
(number, prompt_id, prompt, extra_data, outputs_to_execute)
)
# Backward compatibility: sensitive data handling added in newer ComfyUI
sensitive_keys = getattr(execution, "SENSITIVE_EXTRA_DATA_KEYS", None)
if sensitive_keys:
sensitive = {}
for sensitive_val in sensitive_keys:
if sensitive_val in extra_data:
sensitive[sensitive_val] = extra_data.pop(sensitive_val)
prompt_server.prompt_queue.put(
(
number,
prompt_id,
prompt,
extra_data,
outputs_to_execute,
sensitive,
)
)
else:
# Old ComfyUI version without sensitive data support
prompt_server.prompt_queue.put(
(number, prompt_id, prompt, extra_data, outputs_to_execute)
)
response = {
"prompt_id": prompt_id,
"number": number,
@@ -1323,6 +1327,9 @@ try:
is_async = asyncio.iscoroutinefunction(origin_execute)
if is_async:
# Check signature for backward compatibility (v0.3.67 has 10 params, v0.3.68+ has 11)
sig = inspect.signature(origin_execute)
has_ui_outputs = len(sig.parameters) >= 11
async def swizzle_execute(
server,
@@ -1335,12 +1342,14 @@ try:
execution_list,
pending_subgraph_results,
pending_async_nodes,
ui_outputs=None,
):
unique_id = current_item
class_type = dynprompt.get_node(unique_id)["class_type"]
last_node_id = server.last_node_id
result = await origin_execute(
# Build args list - add ui_outputs only for v0.3.68+
args = [
server,
dynprompt,
caches,
@@ -1351,12 +1360,16 @@ try:
execution_list,
pending_subgraph_results,
pending_async_nodes,
)
]
if has_ui_outputs:
args.append(ui_outputs)
result = await origin_execute(*args)
handle_execute(class_type, last_node_id, prompt_id, server, unique_id)
return result
else:
# Sync version for very old ComfyUI versions
def swizzle_execute(
server,
dynprompt,
@@ -1554,18 +1567,26 @@ async def send_json_override(self, event, data, sid=None):
)
if event == "executing" and data.get("node") is not None:
node = data.get("node")
raw_node = data.get("node")
node = str(raw_node)
if prompt_id in prompt_metadata:
# if 'progress' not in prompt_metadata[prompt_id]:
# prompt_metadata[prompt_id]["progress"] = set()
wf_api = prompt_metadata[prompt_id].workflow_api
# Normalize dotted display ids like "23.0.0.1" to base "23"
if node not in wf_api and "." in node:
base = node.split(".")[0]
if base in wf_api:
node = base
# If still unknown, skip safely
if node not in wf_api:
logger.info(f"Skipping unknown node id in 'executing': {raw_node}")
return
prompt_metadata[prompt_id].progress.add(node)
calculated_progress = len(prompt_metadata[prompt_id].progress) / len(
prompt_metadata[prompt_id].workflow_api
)
calculated_progress = len(prompt_metadata[prompt_id].progress) / len(wf_api)
calculated_progress = round(calculated_progress, 2)
# logger.info("calculated_progress", calculated_progress)
if (
prompt_metadata[prompt_id].last_updated_node is not None
@@ -1573,7 +1594,8 @@ async def send_json_override(self, event, data, sid=None):
):
return
prompt_metadata[prompt_id].last_updated_node = node
class_type = prompt_metadata[prompt_id].workflow_api[node]["class_type"]
class_type = wf_api[node]["class_type"]
logger.info(f"At: {round(calculated_progress * 100)}% - {class_type}")
asyncio.create_task(
send(
+1 -1
View File
@@ -1,7 +1,7 @@
[project]
name = "comfyui-deploy"
description = "Open source comfyui deployment platform, a vercel for generative workflow infra."
version = "2.3.7"
version = "2.3.10"
license = { file = "LICENSE" }
dependencies = ["aiofiles", "pydantic", "opencv-python", "imageio-ffmpeg", "tabulate", "brotli"]