merge
This commit is contained in:
		
						commit
						06805e310d
					
				@ -39,14 +39,34 @@ class ComfyUIDeployExternalImageBatch:
 | 
			
		||||
 | 
			
		||||
    CATEGORY = "image"
 | 
			
		||||
    
 | 
			
		||||
    def process_image(self, image):
 | 
			
		||||
        image = ImageOps.exif_transpose(image)
 | 
			
		||||
        image = image.convert("RGB")
 | 
			
		||||
        image = np.array(image).astype(np.float32) / 255.0
 | 
			
		||||
        image_tensor = torch.from_numpy(image)[None,]
 | 
			
		||||
        return image_tensor
 | 
			
		||||
    
 | 
			
		||||
    def run(self, input_id, images=None, default_value=None, display_name=None, description=None):
 | 
			
		||||
        import requests
 | 
			
		||||
        import zipfile
 | 
			
		||||
        import io
 | 
			
		||||
        
 | 
			
		||||
        processed_images = []
 | 
			
		||||
        try:
 | 
			
		||||
            images_list = json.loads(images)  # Assuming images is a JSON array string
 | 
			
		||||
            print(images_list)
 | 
			
		||||
            for img_input in images_list:
 | 
			
		||||
                if img_input.startswith('http'):
 | 
			
		||||
                    import requests
 | 
			
		||||
                if img_input.startswith('http') and img_input.endswith('.zip'):
 | 
			
		||||
                    print("Fetching zip file from url: ", img_input)
 | 
			
		||||
                    response = requests.get(img_input)
 | 
			
		||||
                    zip_file = zipfile.ZipFile(io.BytesIO(response.content))
 | 
			
		||||
                    for file_name in zip_file.namelist():
 | 
			
		||||
                        if file_name.lower().endswith(('.png', '.jpg', '.jpeg')):
 | 
			
		||||
                            with zip_file.open(file_name) as file:
 | 
			
		||||
                                image = Image.open(file)
 | 
			
		||||
                                image = self.process_image(image)
 | 
			
		||||
                                processed_images.append(image)
 | 
			
		||||
                elif  img_input.startswith('http'):
 | 
			
		||||
                    from io import BytesIO
 | 
			
		||||
                    print("Fetching image from url: ", img_input)
 | 
			
		||||
                    response = requests.get(img_input)
 | 
			
		||||
 | 
			
		||||
@ -28,30 +28,28 @@ from aiohttp import web, ClientSession, ClientError, ClientTimeout
 | 
			
		||||
import atexit
 | 
			
		||||
 | 
			
		||||
# Global session
 | 
			
		||||
client_session = None
 | 
			
		||||
# 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
 | 
			
		||||
#     if client_session is None:
 | 
			
		||||
#         client_session = aiohttp.ClientSession()
 | 
			
		||||
 | 
			
		||||
async def ensure_client_session():
 | 
			
		||||
    global client_session
 | 
			
		||||
    if client_session is None:
 | 
			
		||||
        client_session = aiohttp.ClientSession()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def cleanup():
 | 
			
		||||
    global client_session
 | 
			
		||||
    if client_session:
 | 
			
		||||
        await client_session.close()
 | 
			
		||||
# async def cleanup():
 | 
			
		||||
#     global client_session
 | 
			
		||||
#     if client_session:
 | 
			
		||||
#         await client_session.close()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def exit_handler():
 | 
			
		||||
    print("Exiting the application. Initiating cleanup...")
 | 
			
		||||
    loop = asyncio.get_event_loop()
 | 
			
		||||
    loop.run_until_complete(cleanup())
 | 
			
		||||
    # loop = asyncio.get_event_loop()
 | 
			
		||||
    # loop.run_until_complete(cleanup())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
atexit.register(exit_handler)
 | 
			
		||||
@ -67,8 +65,9 @@ import time
 | 
			
		||||
async def async_request_with_retry(
 | 
			
		||||
    method, url, disable_timeout=False, token=None, **kwargs
 | 
			
		||||
):
 | 
			
		||||
    global client_session
 | 
			
		||||
    await ensure_client_session()
 | 
			
		||||
    # global client_session
 | 
			
		||||
    # await ensure_client_session()
 | 
			
		||||
    async with aiohttp.ClientSession() as client_session:
 | 
			
		||||
        retry_delay = 1  # Start with 1 second delay
 | 
			
		||||
        initial_timeout = 5  # 5 seconds timeout for the initial connection
 | 
			
		||||
 | 
			
		||||
@ -113,7 +112,9 @@ async def async_request_with_retry(
 | 
			
		||||
                )
 | 
			
		||||
            except ClientError as e:
 | 
			
		||||
                end_time = time.time()
 | 
			
		||||
            logger.error(f"Request failed (attempt {attempt + 1}/{max_retries}): {e}")
 | 
			
		||||
                logger.error(
 | 
			
		||||
                    f"Request failed (attempt {attempt + 1}/{max_retries}): {e}"
 | 
			
		||||
                )
 | 
			
		||||
                logger.error(
 | 
			
		||||
                    f"Time taken for failed attempt: {end_time - request_start:.2f} seconds"
 | 
			
		||||
                )
 | 
			
		||||
@ -1621,6 +1622,8 @@ async def update_run_with_output(
 | 
			
		||||
        "node_meta": node_meta,
 | 
			
		||||
        "gpu_event_id": gpu_event_id,
 | 
			
		||||
    }
 | 
			
		||||
    have_upload_media = False
 | 
			
		||||
    if data is not None:
 | 
			
		||||
        have_upload_media = (
 | 
			
		||||
            "images" in data or "files" in data or "gifs" in data or "mesh" in data
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
@ -192,11 +192,13 @@ const ext = {
 | 
			
		||||
 | 
			
		||||
  registerCustomNodes() {
 | 
			
		||||
    /** @type {LGraphNode}*/
 | 
			
		||||
    class ComfyDeploy {
 | 
			
		||||
      color = LGraphCanvas.node_colors.yellow.color;
 | 
			
		||||
      bgcolor = LGraphCanvas.node_colors.yellow.bgcolor;
 | 
			
		||||
      groupcolor = LGraphCanvas.node_colors.yellow.groupcolor;
 | 
			
		||||
    class ComfyDeploy extends LGraphNode {
 | 
			
		||||
      constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
        this.color = LGraphCanvas.node_colors.yellow.color;
 | 
			
		||||
        this.bgcolor = LGraphCanvas.node_colors.yellow.bgcolor;
 | 
			
		||||
        this.groupcolor = LGraphCanvas.node_colors.yellow.groupcolor;
 | 
			
		||||
 | 
			
		||||
        if (!this.properties) {
 | 
			
		||||
          this.properties = {};
 | 
			
		||||
          this.properties.workflow_name = "";
 | 
			
		||||
@ -204,65 +206,75 @@ const ext = {
 | 
			
		||||
          this.properties.version = "";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ComfyWidgets.STRING(
 | 
			
		||||
          this,
 | 
			
		||||
        this.addWidget(
 | 
			
		||||
          "text",
 | 
			
		||||
          "workflow_name",
 | 
			
		||||
          [
 | 
			
		||||
            "",
 | 
			
		||||
            {
 | 
			
		||||
              default: this.properties.workflow_name,
 | 
			
		||||
              multiline: false,
 | 
			
		||||
          this.properties.workflow_name,
 | 
			
		||||
          (v) => {
 | 
			
		||||
            this.properties.workflow_name = v;
 | 
			
		||||
          },
 | 
			
		||||
          ],
 | 
			
		||||
          app,
 | 
			
		||||
          { multiline: false }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        ComfyWidgets.STRING(
 | 
			
		||||
          this,
 | 
			
		||||
        this.addWidget(
 | 
			
		||||
          "text",
 | 
			
		||||
          "workflow_id",
 | 
			
		||||
          [
 | 
			
		||||
            "",
 | 
			
		||||
            {
 | 
			
		||||
              default: this.properties.workflow_id,
 | 
			
		||||
              multiline: false,
 | 
			
		||||
          this.properties.workflow_id,
 | 
			
		||||
          (v) => {
 | 
			
		||||
            this.properties.workflow_id = v;
 | 
			
		||||
          },
 | 
			
		||||
          ],
 | 
			
		||||
          app,
 | 
			
		||||
          { multiline: false }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        ComfyWidgets.STRING(
 | 
			
		||||
          this,
 | 
			
		||||
        this.addWidget(
 | 
			
		||||
          "text",
 | 
			
		||||
          "version",
 | 
			
		||||
          ["", { default: this.properties.version, multiline: false }],
 | 
			
		||||
          app,
 | 
			
		||||
          this.properties.version,
 | 
			
		||||
          (v) => {
 | 
			
		||||
            this.properties.version = v;
 | 
			
		||||
          },
 | 
			
		||||
          { multiline: false }
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // this.widgets.forEach((w) => {
 | 
			
		||||
        //   // w.computeSize = () => [200,10]
 | 
			
		||||
        //   w.computedHeight = 2;
 | 
			
		||||
        // })
 | 
			
		||||
 | 
			
		||||
        this.widgets_start_y = 10;
 | 
			
		||||
        this.setSize(this.computeSize());
 | 
			
		||||
 | 
			
		||||
        // const config = {  };
 | 
			
		||||
 | 
			
		||||
        // console.log(this);
 | 
			
		||||
        this.serialize_widgets = true;
 | 
			
		||||
        this.isVirtualNode = true;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      onExecute() {
 | 
			
		||||
        // This method is called when the node is executed
 | 
			
		||||
        // You can add any necessary logic here
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    // Load default visibility
 | 
			
		||||
      onSerialize(o) {
 | 
			
		||||
        // This method is called when the node is being serialized
 | 
			
		||||
        // Ensure all necessary data is saved
 | 
			
		||||
        if (!o.properties) {
 | 
			
		||||
          o.properties = {};
 | 
			
		||||
        }
 | 
			
		||||
        o.properties.workflow_name = this.properties.workflow_name;
 | 
			
		||||
        o.properties.workflow_id = this.properties.workflow_id;
 | 
			
		||||
        o.properties.version = this.properties.version;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    LiteGraph.registerNodeType(
 | 
			
		||||
      "ComfyDeploy",
 | 
			
		||||
      Object.assign(ComfyDeploy, {
 | 
			
		||||
        title_mode: LiteGraph.NORMAL_TITLE,
 | 
			
		||||
      onConfigure(o) {
 | 
			
		||||
        // This method is called when the node is being configured (e.g., when loading a saved graph)
 | 
			
		||||
        // Ensure all necessary data is restored
 | 
			
		||||
        if (o.properties) {
 | 
			
		||||
          this.properties = { ...this.properties, ...o.properties };
 | 
			
		||||
          this.widgets[0].value = this.properties.workflow_name || "";
 | 
			
		||||
          this.widgets[1].value = this.properties.workflow_id || "";
 | 
			
		||||
          this.widgets[2].value = this.properties.version || "1";
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Register the node type
 | 
			
		||||
    LiteGraph.registerNodeType("ComfyDeploy", Object.assign(ComfyDeploy, {
 | 
			
		||||
      title: "Comfy Deploy",
 | 
			
		||||
      title_mode: LiteGraph.NORMAL_TITLE,
 | 
			
		||||
      collapsable: true,
 | 
			
		||||
      }),
 | 
			
		||||
    );
 | 
			
		||||
    }));
 | 
			
		||||
 | 
			
		||||
    ComfyDeploy.category = "deploy";
 | 
			
		||||
  },
 | 
			
		||||
@ -442,14 +454,11 @@ function createDynamicUIHtml(data) {
 | 
			
		||||
  Object.values(data.custom_nodes).forEach((node) => {
 | 
			
		||||
    html += `
 | 
			
		||||
          <div style="border-bottom: 1px solid #e2e8f0; padding-top: 16px;">
 | 
			
		||||
              <a href="${
 | 
			
		||||
                node.url
 | 
			
		||||
              }" target="_blank" style="font-size: 18px; font-weight: semibold; color: white; text-decoration: none;">${
 | 
			
		||||
                node.name
 | 
			
		||||
              <a href="${node.url
 | 
			
		||||
      }" target="_blank" style="font-size: 18px; font-weight: semibold; color: white; text-decoration: none;">${node.name
 | 
			
		||||
      }</a>
 | 
			
		||||
              <p style="font-size: 14px; color: #4b5563;">${node.hash}</p>
 | 
			
		||||
              ${
 | 
			
		||||
                node.warning
 | 
			
		||||
              ${node.warning
 | 
			
		||||
        ? `<p style="font-size: 14px; color: #d69e2e;">${node.warning}</p>`
 | 
			
		||||
        : ""
 | 
			
		||||
      }
 | 
			
		||||
@ -466,8 +475,7 @@ function createDynamicUIHtml(data) {
 | 
			
		||||
  Object.entries(data.models).forEach(([section, items]) => {
 | 
			
		||||
    html += `
 | 
			
		||||
    <div style="border-bottom: 1px solid #e2e8f0; padding-top: 8px; padding-bottom: 8px;">
 | 
			
		||||
        <h3 style="font-size: 18px; font-weight: semibold; margin-bottom: 8px;">${
 | 
			
		||||
          section.charAt(0).toUpperCase() + section.slice(1)
 | 
			
		||||
        <h3 style="font-size: 18px; font-weight: semibold; margin-bottom: 8px;">${section.charAt(0).toUpperCase() + section.slice(1)
 | 
			
		||||
      }</h3>`;
 | 
			
		||||
    items.forEach((item) => {
 | 
			
		||||
      html += `<p style="font-size: 14px; color: ${textColor};">${item.name}</p>`;
 | 
			
		||||
@ -484,8 +492,7 @@ function createDynamicUIHtml(data) {
 | 
			
		||||
  Object.entries(data.files).forEach(([section, items]) => {
 | 
			
		||||
    html += `
 | 
			
		||||
    <div style="border-bottom: 1px solid #e2e8f0; padding-top: 8px; padding-bottom: 8px;">
 | 
			
		||||
        <h3 style="font-size: 18px; font-weight: semibold; margin-bottom: 8px;">${
 | 
			
		||||
          section.charAt(0).toUpperCase() + section.slice(1)
 | 
			
		||||
        <h3 style="font-size: 18px; font-weight: semibold; margin-bottom: 8px;">${section.charAt(0).toUpperCase() + section.slice(1)
 | 
			
		||||
      }</h3>`;
 | 
			
		||||
    items.forEach((item) => {
 | 
			
		||||
      html += `<p style="font-size: 14px; color: ${textColor};">${item.name}</p>`;
 | 
			
		||||
@ -1006,11 +1013,9 @@ export class LoadingDialog extends ComfyDialog {
 | 
			
		||||
  showLoading(title, message) {
 | 
			
		||||
    this.show(`
 | 
			
		||||
      <div style="width: 400px; display: flex; gap: 18px; flex-direction: column; overflow: unset">
 | 
			
		||||
        <h3 style="margin: 0px; display: flex; align-items: center; justify-content: center; gap: 12px;">${title} ${
 | 
			
		||||
          this.loadingIcon
 | 
			
		||||
        <h3 style="margin: 0px; display: flex; align-items: center; justify-content: center; gap: 12px;">${title} ${this.loadingIcon
 | 
			
		||||
      }</h3>
 | 
			
		||||
          ${
 | 
			
		||||
            message
 | 
			
		||||
          ${message
 | 
			
		||||
        ? `<label style="max-width: 100%; white-space: pre-wrap; word-wrap: break-word;">${message}</label>`
 | 
			
		||||
        : ""
 | 
			
		||||
      }
 | 
			
		||||
@ -1279,20 +1284,16 @@ export class ConfigDialog extends ComfyDialog {
 | 
			
		||||
    </label>
 | 
			
		||||
      <label style="color: white; width: 100%;">
 | 
			
		||||
        Endpoint:
 | 
			
		||||
        <input id="endpoint" style="margin-top: 8px; width: 100%; height:40px; box-sizing: border-box; padding: 0px 6px;" type="text" value="${
 | 
			
		||||
          data.endpoint
 | 
			
		||||
        <input id="endpoint" style="margin-top: 8px; width: 100%; height:40px; box-sizing: border-box; padding: 0px 6px;" type="text" value="${data.endpoint
 | 
			
		||||
      }">
 | 
			
		||||
      </label>
 | 
			
		||||
      <div style="color: white;">
 | 
			
		||||
        API Key: User / Org <button style="font-size: 18px;">${
 | 
			
		||||
          data.displayName ?? ""
 | 
			
		||||
        API Key: User / Org <button style="font-size: 18px;">${data.displayName ?? ""
 | 
			
		||||
      }</button>
 | 
			
		||||
        <input id="apiKey" style="margin-top: 8px; width: 100%; height:40px; box-sizing: border-box; padding: 0px 6px;" type="password" value="${
 | 
			
		||||
          data.apiKey
 | 
			
		||||
        <input id="apiKey" style="margin-top: 8px; width: 100%; height:40px; box-sizing: border-box; padding: 0px 6px;" type="password" value="${data.apiKey
 | 
			
		||||
      }">
 | 
			
		||||
        <button id="loginButton" style="margin-top: 8px; width: 100%; height:40px; box-sizing: border-box; padding: 0px 6px;">
 | 
			
		||||
          ${
 | 
			
		||||
            data.apiKey ? "Re-login with ComfyDeploy" : "Login with ComfyDeploy"
 | 
			
		||||
          ${data.apiKey ? "Re-login with ComfyDeploy" : "Login with ComfyDeploy"
 | 
			
		||||
      }
 | 
			
		||||
        </button>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user