fix: preserve multimodal user content during persistence

Avoid applying text-only persist_user_message overrides to multimodal current-turn user messages. Early crash-resilience persistence mutates the same messages list later used for the API call, so clobbering list content drops ACP image blocks before model dispatch.\n\nAdd regression coverage for both text override behavior and multimodal preservation.\n\nCloses #44242
This commit is contained in:
Reiji Kisaragi 2026-06-11 18:56:32 +07:00 committed by Teknium
parent c2fa302e93
commit 3d21666b2f
2 changed files with 36 additions and 1 deletions

View file

@ -1483,7 +1483,15 @@ class AIAgent:
if 0 <= idx < len(messages):
msg = messages[idx]
if isinstance(msg, dict) and msg.get("role") == "user":
if override is not None:
# Text-only call paths may pass a synthetic API-facing prompt
# and a cleaner transcript string separately. Multimodal
# turns, however, keep image/audio blocks in the live
# messages list that is still used for the API request after
# early crash-resilience persistence. Do not replace those
# blocks with the text-only persistence override before the
# model call is built. The paired timestamp override still
# applies — it is metadata, not content.
if override is not None and not isinstance(msg.get("content"), list):
msg["content"] = override
if timestamp is not None:
msg["timestamp"] = timestamp

View file

@ -75,6 +75,33 @@ def agent():
return a
def test_persist_user_message_override_rewrites_text_turns(agent):
messages = [{"role": "user", "content": "API-only synthetic prefix\nhello"}]
agent._persist_user_message_idx = 0
agent._persist_user_message_override = "hello"
agent._apply_persist_user_message_override(messages)
assert messages == [{"role": "user", "content": "hello"}]
def test_persist_user_message_override_preserves_multimodal_turns(agent):
multimodal_content = [
{"type": "text", "text": "What color is this?"},
{
"type": "image_url",
"image_url": {"url": "data:image/png;base64,AAAA"},
},
]
messages = [{"role": "user", "content": multimodal_content}]
agent._persist_user_message_idx = 0
agent._persist_user_message_override = "What color is this? [Image attachment]"
agent._apply_persist_user_message_override(messages)
assert messages == [{"role": "user", "content": multimodal_content}]
@pytest.fixture()
def agent_with_memory_tool():
"""Agent whose valid_tool_names includes 'memory'."""