feat(webui): support image uploads in composer and message bubbles
This commit is contained in:
@@ -217,3 +217,55 @@ def test_window_cuts_mid_tool_group():
|
||||
# leaving orphan tool results for split_a at the front.
|
||||
history = session.get_history(max_messages=6)
|
||||
_assert_no_orphans(history)
|
||||
|
||||
|
||||
# --- Image breadcrumbs: media kwarg is synthesized into content for replay ---
|
||||
|
||||
|
||||
def test_get_history_synthesizes_image_breadcrumb_from_media_kwarg():
|
||||
"""Persisted user turns carry image paths as a ``media`` kwarg; LLM
|
||||
replay must still see an ``[image: path]`` breadcrumb so the assistant's
|
||||
follow-up reply has a referent instead of trailing an empty user row."""
|
||||
session = Session(key="test:media")
|
||||
session.messages.append(
|
||||
{"role": "user", "content": "look", "media": ["/m/a.png", "/m/b.png"]}
|
||||
)
|
||||
session.messages.append({"role": "assistant", "content": "nice"})
|
||||
|
||||
history = session.get_history(max_messages=500)
|
||||
|
||||
assert history == [
|
||||
{"role": "user", "content": "look\n[image: /m/a.png]\n[image: /m/b.png]"},
|
||||
{"role": "assistant", "content": "nice"},
|
||||
]
|
||||
|
||||
|
||||
def test_get_history_synthesizes_breadcrumb_for_image_only_turn():
|
||||
"""Turns with no text but attached images must not replay as empty
|
||||
strings — the LLM would otherwise see a bare user turn followed by an
|
||||
unexplained assistant answer."""
|
||||
session = Session(key="test:image-only")
|
||||
session.messages.append({"role": "user", "content": "", "media": ["/m/pic.png"]})
|
||||
session.messages.append({"role": "assistant", "content": "I see a cat"})
|
||||
|
||||
history = session.get_history(max_messages=500)
|
||||
|
||||
assert history[0] == {"role": "user", "content": "[image: /m/pic.png]"}
|
||||
|
||||
|
||||
def test_get_history_ignores_media_kwarg_on_non_user_rows():
|
||||
"""``media`` only ever appears on user entries in practice, but the
|
||||
synthesizer must be defensive: assistants / tools with list content
|
||||
don't get the breadcrumb pasted on top."""
|
||||
session = Session(key="test:defensive")
|
||||
session.messages.append(
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": [{"type": "text", "text": "structured"}],
|
||||
"media": ["/m/x.png"], # nonsense but shouldn't crash
|
||||
}
|
||||
)
|
||||
history = session.get_history(max_messages=500)
|
||||
# List content is passed through verbatim — the synthesizer only
|
||||
# rewrites plain-string content.
|
||||
assert history[0]["content"] == [{"type": "text", "text": "structured"}]
|
||||
|
||||
Reference in New Issue
Block a user