Image tools: work around OWUI 0.9.x files-event regression
Open WebUI 0.9.0 introduced chat-history virtualization that unmounts off-screen assistant messages and reconstructs them from persisted shape; `files` attached mid-stream by a tool don't survive the round-trip — the image flashes in during streaming and disappears the moment the message commits. Both image tools now upload via Open WebUI's file store as before but surface the result as a markdown image injected into the assistant message via a `message` event, which is part of the persisted shape and renders reliably across remounts. Trade-off: loses the file-attachment chrome (thumbnail + download button). Each tool has a TODO marking the swap site with the original `files` payload inlined for one-line revert once upstream fixes the regression. smart_image_gen.py 0.7.8 -> 0.7.9 smart_image_pipe.py 0.1.0 -> 0.1.1 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
title: Smart Image Generator & Editor (ComfyUI)
|
title: Smart Image Generator & Editor (ComfyUI)
|
||||||
author: ai-stack
|
author: ai-stack
|
||||||
version: 0.7.8
|
version: 0.7.9
|
||||||
description: Generate or edit images via ComfyUI with automatic SDXL
|
description: Generate or edit images via ComfyUI with automatic SDXL
|
||||||
checkpoint routing. Two methods — generate_image (txt2img) and
|
checkpoint routing. Two methods — generate_image (txt2img) and
|
||||||
edit_image (img2img on the user's most recently attached image). The
|
edit_image (img2img on the user's most recently attached image). The
|
||||||
@@ -9,8 +9,8 @@ description: Generate or edit images via ComfyUI with automatic SDXL
|
|||||||
score-tag, NoobAI/Illustrious furry, etc. — and each style ships
|
score-tag, NoobAI/Illustrious furry, etc. — and each style ships
|
||||||
with the creator-recommended sampler, scheduler, CFG, steps, CLIP
|
with the creator-recommended sampler, scheduler, CFG, steps, CLIP
|
||||||
skip, prompt-prefix dialect, and negatives. The image is uploaded
|
skip, prompt-prefix dialect, and negatives. The image is uploaded
|
||||||
to Open WebUI's file store and surfaced via a `files` event (the
|
to Open WebUI's file store and surfaced as a markdown image
|
||||||
canonical pattern used by Open WebUI's own image-gen path); the
|
appended to the assistant message via a `message` event; the
|
||||||
function return is a short confirmation so the LLM doesn't try to
|
function return is a short confirmation so the LLM doesn't try to
|
||||||
describe or re-emit the image.
|
describe or re-emit the image.
|
||||||
required_open_webui_version: 0.5.0
|
required_open_webui_version: 0.5.0
|
||||||
@@ -586,14 +586,22 @@ async def _push_image_to_chat(
|
|||||||
event_emitter: Optional[Callable[[dict], Awaitable[None]]],
|
event_emitter: Optional[Callable[[dict], Awaitable[None]]],
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Surface a generated image in the chat using Open WebUI's canonical
|
Surface a generated image in the chat: upload the bytes via the
|
||||||
pattern: upload the bytes via the internal file store, then emit a
|
internal file store, then inject a markdown image referencing the
|
||||||
`files` event referencing the served URL. This is the same path Open
|
served URL into the assistant message via a `message` event.
|
||||||
WebUI's own image-generation code uses (utils/middleware.py ~1325).
|
|
||||||
|
|
||||||
Returns True if the image was uploaded and emitted via the files
|
We deliberately don't use the `files` event (Open WebUI's own
|
||||||
event. Returns False if anything is missing — caller should fall
|
image-gen path). Open WebUI 0.9.x added chat-history virtualization
|
||||||
back to a data-URI markdown message in that case.
|
that unmounts off-screen messages and reconstructs them from
|
||||||
|
persisted shape — and `files` attached to an assistant message
|
||||||
|
mid-stream by a tool don't survive that round-trip. The image
|
||||||
|
flashes in during streaming and disappears the moment the message
|
||||||
|
commits. Markdown in `message.content` is part of the persisted
|
||||||
|
shape, so it renders reliably on every remount.
|
||||||
|
|
||||||
|
Returns True if the image was uploaded and emitted. Returns False
|
||||||
|
if anything is missing — caller falls back to a data-URI markdown
|
||||||
|
message (same `message` event path, just inline bytes).
|
||||||
"""
|
"""
|
||||||
if not (_OPENWEBUI_RUNTIME and request and user_dict and event_emitter):
|
if not (_OPENWEBUI_RUNTIME and request and user_dict and event_emitter):
|
||||||
return False
|
return False
|
||||||
@@ -630,9 +638,23 @@ async def _push_image_to_chat(
|
|||||||
"get_file_content_by_id", id=file_item.id
|
"get_file_content_by_id", id=file_item.id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# TODO(open-webui virtualization fix): once chat-history
|
||||||
|
# virtualization survives `files` events from tool calls again,
|
||||||
|
# swap back to the `files` payload below. The `files` event
|
||||||
|
# gives proper file-attachment chrome (thumbnail card + download
|
||||||
|
# button) that the markdown-image path lacks. Verify the fix by
|
||||||
|
# emitting `files`, then refreshing the page AND scrolling the
|
||||||
|
# message off-screen and back — both must keep the image
|
||||||
|
# visible. Track upstream: github.com/open-webui/open-webui
|
||||||
|
# release notes mentioning tool calls, `files` events, or
|
||||||
|
# virtualization. To restore, replace the block below with:
|
||||||
|
# await event_emitter({
|
||||||
|
# "type": "files",
|
||||||
|
# "data": {"files": [{"type": "image", "url": url}]},
|
||||||
|
# })
|
||||||
await event_emitter({
|
await event_emitter({
|
||||||
"type": "files",
|
"type": "message",
|
||||||
"data": {"files": [{"type": "image", "url": url}]},
|
"data": {"content": f"\n\n"},
|
||||||
})
|
})
|
||||||
return True
|
return True
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
title: Smart Image Studio (Pipe)
|
title: Smart Image Studio (Pipe)
|
||||||
author: ai-stack
|
author: ai-stack
|
||||||
version: 0.1.0
|
version: 0.1.1
|
||||||
description: Deterministic image-gen / edit / inpaint pipe — no LLM in the
|
description: Deterministic image-gen / edit / inpaint pipe — no LLM in the
|
||||||
loop for the routing decision. Registers as a model in the chat-model
|
loop for the routing decision. Registers as a model in the chat-model
|
||||||
dropdown ('Image Studio (Pipe)'). Reads the user's message + attached
|
dropdown ('Image Studio (Pipe)'). Reads the user's message + attached
|
||||||
@@ -420,9 +420,23 @@ async def _push_image_to_chat(raw, prefix, request, user_dict, metadata, event_e
|
|||||||
)
|
)
|
||||||
file_item = await result if inspect.iscoroutine(result) else result
|
file_item = await result if inspect.iscoroutine(result) else result
|
||||||
url = request.app.url_path_for("get_file_content_by_id", id=file_item.id)
|
url = request.app.url_path_for("get_file_content_by_id", id=file_item.id)
|
||||||
|
# TODO(open-webui virtualization fix): once chat-history
|
||||||
|
# virtualization survives `files` events from tool calls again,
|
||||||
|
# swap back to the `files` payload below. The `files` event
|
||||||
|
# gives proper file-attachment chrome (thumbnail card + download
|
||||||
|
# button) that the markdown-image path lacks. Verify the fix by
|
||||||
|
# emitting `files`, then refreshing the page AND scrolling the
|
||||||
|
# message off-screen and back — both must keep the image
|
||||||
|
# visible. Track upstream: github.com/open-webui/open-webui
|
||||||
|
# release notes mentioning tool calls, `files` events, or
|
||||||
|
# virtualization. To restore, replace the block below with:
|
||||||
|
# await event_emitter({
|
||||||
|
# "type": "files",
|
||||||
|
# "data": {"files": [{"type": "image", "url": url}]},
|
||||||
|
# })
|
||||||
await event_emitter({
|
await event_emitter({
|
||||||
"type": "files",
|
"type": "message",
|
||||||
"data": {"files": [{"type": "image", "url": url}]},
|
"data": {"content": f"\n\n"},
|
||||||
})
|
})
|
||||||
return True
|
return True
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|||||||
Reference in New Issue
Block a user