From a1af88a6323fede0778a40073c28686b4ae92421 Mon Sep 17 00:00:00 2001 From: William Gill Date: Sun, 19 Apr 2026 18:22:45 -0500 Subject: [PATCH] smart_image_gen v0.7.8: per-job filename_prefix + source-image diagnostic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User reported observing a wrong image returned. Two hardenings: 1. _job_prefix() generates a per-submission filename_prefix ('smartedit_<10hex>', 'smartinpaint_<10hex>', 'smartgen_<10hex>') so SaveImage outputs from concurrent jobs sit in their own namespace and ComfyUI's auto-incrementing counter can never produce filenames that overlap across jobs. With a shared prefix, if a queued job's history-fetch ever raced past its own SaveImage record there was a theoretical (if unlikely) path to picking up another job's _00001_.png. Per-job prefix kills that vector. 2. edit_image now emits the source image's SHA-1 and byte count in a status event before uploading to ComfyUI. If a future 'wrong image' report comes in, that hash should match the prior generation's output — if it doesn't, we know _extract_attached_image picked up the wrong source rather than ComfyUI returning the wrong file. Hashlib import is local so the module's import surface stays clean. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../openwebui-tools/smart_image_gen.py | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/deployments/ai-stack/openwebui-tools/smart_image_gen.py b/deployments/ai-stack/openwebui-tools/smart_image_gen.py index 8ca9289..6edffa2 100644 --- a/deployments/ai-stack/openwebui-tools/smart_image_gen.py +++ b/deployments/ai-stack/openwebui-tools/smart_image_gen.py @@ -1,7 +1,7 @@ """ title: Smart Image Generator & Editor (ComfyUI) author: ai-stack -version: 0.7.7 +version: 0.7.8 description: Generate or edit images via ComfyUI with automatic SDXL checkpoint routing. Two methods — generate_image (txt2img) and edit_image (img2img on the user's most recently attached image). The @@ -263,6 +263,12 @@ def _seed_value(seed: int) -> int: return seed if seed > 0 else int(time.time() * 1000) % (2**31) +def _job_prefix(kind: str) -> str: + """Per-submission filename_prefix so SaveImage outputs from concurrent + jobs can never share an auto-numbered counter and cross over.""" + return f"{kind}_{uuid.uuid4().hex[:10]}" + + def _build_txt2img(positive: str, negative: str, settings: dict, width: int, height: int, seed: int) -> dict: """ @@ -286,7 +292,7 @@ def _build_txt2img(positive: str, negative: str, settings: dict, "7": {"class_type": "CLIPTextEncode", "inputs": {"text": negative, "clip": ["10", 0]}}, "8": {"class_type": "VAEDecode", "inputs": {"samples": ["3", 0], "vae": ["4", 2]}}, "9": {"class_type": "SaveImage", - "inputs": {"filename_prefix": "smartgen", "images": ["8", 0]}}, + "inputs": {"filename_prefix": _job_prefix("smartgen"), "images": ["8", 0]}}, "10": {"class_type": "CLIPSetLastLayer", "inputs": {"stop_at_clip_layer": -settings["clip_skip"], "clip": ["4", 1]}}, @@ -329,7 +335,7 @@ def _build_inpaint(positive: str, negative: str, settings: dict, "7": {"class_type": "CLIPTextEncode", "inputs": {"text": negative, "clip": ["10", 0]}}, "8": {"class_type": "VAEDecode", "inputs": {"samples": ["3", 0], "vae": ["4", 2]}}, "9": {"class_type": "SaveImage", - "inputs": {"filename_prefix": "smartinpaint", "images": ["8", 0]}}, + "inputs": {"filename_prefix": _job_prefix("smartinpaint"), "images": ["8", 0]}}, "10": {"class_type": "CLIPSetLastLayer", "inputs": {"stop_at_clip_layer": -settings["clip_skip"], "clip": ["4", 1]}}, @@ -381,7 +387,7 @@ def _build_img2img(positive: str, negative: str, settings: dict, "7": {"class_type": "CLIPTextEncode", "inputs": {"text": negative, "clip": ["10", 0]}}, "8": {"class_type": "VAEDecode", "inputs": {"samples": ["3", 0], "vae": ["4", 2]}}, "9": {"class_type": "SaveImage", - "inputs": {"filename_prefix": "smartedit", "images": ["8", 0]}}, + "inputs": {"filename_prefix": _job_prefix("smartedit"), "images": ["8", 0]}}, "10": {"class_type": "CLIPSetLastLayer", "inputs": {"stop_at_clip_layer": -settings["clip_skip"], "clip": ["4", 1]}}, @@ -943,7 +949,14 @@ class Tools: "(paperclip / drag-drop), or call generate_image instead." ) - await emit("Uploading source to ComfyUI…") + # Diagnostic emit so a misrouted source ("wrong image + # returned") shows up in the status track instead of being + # invisible. SHA-1 is fast and the first 8 hex chars are + # plenty to compare against the prior generation's hash if + # cross-talk is suspected. + import hashlib # local import — keeps the module import surface clean + src_hash = hashlib.sha1(raw_in).hexdigest()[:8] + await emit(f"Uploading source to ComfyUI… (sha1={src_hash}, {len(raw_in)} bytes)") uploaded_name = await _upload_to_comfyui(session, base, raw_in) if not uploaded_name: return "Failed to upload source image to ComfyUI."