import json import logging import requests from flask import current_app from services.workflow import NODE_CHECKPOINT logger = logging.getLogger('gaze') def get_loaded_checkpoint(): """Return the checkpoint path currently loaded in ComfyUI, or None.""" try: url = current_app.config.get('COMFYUI_URL', 'http://127.0.0.1:8188') resp = requests.get(f'{url}/history', timeout=3) if resp.ok: history = resp.json() if history: # Sort by prompt ID (numeric string) to get the most recent job latest_id = max(history.keys()) latest = history[latest_id] nodes = latest.get('prompt', [None, None, {}])[2] return nodes.get(NODE_CHECKPOINT, {}).get('inputs', {}).get('ckpt_name') except Exception: pass return None def _ensure_checkpoint_loaded(checkpoint_path): """Check if the desired checkpoint is loaded in ComfyUI, and force reload if not.""" if not checkpoint_path: return try: # Get currently loaded checkpoint from ComfyUI history url = current_app.config.get('COMFYUI_URL', 'http://127.0.0.1:8188') resp = requests.get(f'{url}/history', timeout=3) if resp.ok: history = resp.json() if history: latest_id = max(history.keys()) latest = history[latest_id] nodes = latest.get('prompt', [None, None, {}])[2] loaded_ckpt = nodes.get(NODE_CHECKPOINT, {}).get('inputs', {}).get('ckpt_name') # If the loaded checkpoint matches what we want, no action needed if loaded_ckpt == checkpoint_path: logger.info("Checkpoint %s already loaded in ComfyUI", checkpoint_path) return # Checkpoint doesn't match or couldn't determine - force unload all models logger.info("Forcing ComfyUI to unload models to ensure %s loads", checkpoint_path) requests.post(f'{url}/free', json={'unload_models': True}, timeout=5) except Exception as e: logger.warning("Failed to check/force checkpoint reload: %s", e) def queue_prompt(prompt_workflow, client_id=None): """POST a workflow to ComfyUI's /prompt endpoint.""" # Ensure the checkpoint in the workflow is loaded in ComfyUI checkpoint_path = prompt_workflow.get(NODE_CHECKPOINT, {}).get('inputs', {}).get('ckpt_name') _ensure_checkpoint_loaded(checkpoint_path) p = {"prompt": prompt_workflow} if client_id: p["client_id"] = client_id url = current_app.config['COMFYUI_URL'] # Log the full request being sent to ComfyUI logger.debug("=" * 80) logger.debug("COMFYUI REQUEST - Sending prompt to %s/prompt", url) logger.debug("Checkpoint: %s", checkpoint_path) logger.debug("Client ID: %s", client_id if client_id else "(none)") logger.debug("Full workflow JSON:") logger.debug(json.dumps(prompt_workflow, indent=2)) logger.debug("=" * 80) data = json.dumps(p).encode('utf-8') response = requests.post(f"{url}/prompt", data=data, timeout=30) if not response.ok: logger.error("ComfyUI returned HTTP %s: %s", response.status_code, response.text[:500]) raise RuntimeError(f"ComfyUI returned HTTP {response.status_code}") response_json = response.json() # Log the response from ComfyUI logger.debug("COMFYUI RESPONSE - Status: %s", response.status_code) logger.debug("Response JSON: %s", json.dumps(response_json, indent=2)) if 'prompt_id' in response_json: logger.info("ComfyUI accepted prompt with ID: %s", response_json['prompt_id']) else: logger.error("ComfyUI rejected prompt: %s", response_json) logger.debug("=" * 80) return response_json def get_history(prompt_id): """Poll ComfyUI /history for results of a given prompt_id.""" url = current_app.config['COMFYUI_URL'] response = requests.get(f"{url}/history/{prompt_id}", timeout=10) history_json = response.json() # Log detailed history response for debugging if prompt_id in history_json: logger.debug("=" * 80) logger.debug("COMFYUI HISTORY - Prompt ID: %s", prompt_id) logger.debug("Status: %s", response.status_code) # Extract key information from the history prompt_data = history_json[prompt_id] if 'status' in prompt_data: logger.debug("Generation status: %s", prompt_data['status']) if 'outputs' in prompt_data: logger.debug("Outputs available: %s", list(prompt_data['outputs'].keys())) for node_id, output in prompt_data['outputs'].items(): if 'images' in output: logger.debug(" Node %s produced %d image(s)", node_id, len(output['images'])) for img in output['images']: logger.debug(" - %s (subfolder: %s, type: %s)", img.get('filename'), img.get('subfolder'), img.get('type')) logger.debug("Full history response:") logger.debug(json.dumps(history_json, indent=2)) logger.debug("=" * 80) else: logger.debug("History not yet available for prompt ID: %s", prompt_id) return history_json def get_image(filename, subfolder, folder_type): """Retrieve a generated image from ComfyUI's /view endpoint.""" url = current_app.config['COMFYUI_URL'] data = {"filename": filename, "subfolder": subfolder, "type": folder_type} logger.debug("Fetching image from ComfyUI: filename=%s, subfolder=%s, type=%s", filename, subfolder, folder_type) response = requests.get(f"{url}/view", params=data, timeout=30) logger.debug("Image retrieved: %d bytes (status: %s)", len(response.content), response.status_code) return response.content