Skip to content

fix(agent): don't clobber multimodal user content with persist_user_message override#44248

Closed
AIalliAI wants to merge 1 commit into
NousResearch:mainfrom
AIalliAI:fix/44242-acp-image-persist-override
Closed

fix(agent): don't clobber multimodal user content with persist_user_message override#44248
AIalliAI wants to merge 1 commit into
NousResearch:mainfrom
AIalliAI:fix/44242-acp-image-persist-override

Conversation

@AIalliAI

Copy link
Copy Markdown
Contributor

Summary

Image content blocks sent through the ACP adapter never reached the model: build_turn_context runs a crash-resilience persist of the inbound user turn before the first API call, and _persist_session_apply_persist_user_message_override mutates the same messages list the request is later built from. The ACP adapter passes a text-only persist_user_message for multimodal prompts (acp_adapter/server.py), so the [{type:"text"}, {type:"image_url"}] content list was replaced with a plain string before any provider call — the image was dropped end-to-end, on every provider, regardless of vision support.

Fix

_apply_persist_user_message_override now leaves content-part lists untouched. The synthetic-prefix cleanup the override exists for (voice prefix in cli.py, ACP steering text) only ever applies to string-content turns, and image redaction for the session DB already happens downstream in _flush_messages_to_session_db (images → [screenshot] placeholder), so DB bloat is not a concern.

Verification

  • Traced the full path on main: ACP _content_blocks_to_openai_user_content produces the multimodal list → turn_context.py early _persist_session (crash-resilience persist) → override clobbers msg["content"] before the request is assembled.
  • New regression test: multimodal user turn keeps its image_url part through _persist_session, while the DB write still gets the redacted text form.
  • Existing TestPersistUserMessageOverride text-turn test unchanged and passing — voice-prefix/steering cleanup behavior is preserved.
  • tests/run_agent/ + tests/agent/test_turn_context.py: 1627 passed, 2 failed — the two test_provider_parity.py::TestAuxiliaryClientProviderPriority failures are pre-existing test-ordering pollution (they fail identically on pristine origin/main in a full-suite run and pass in isolation both with and without this change).

Fixes #44242

🤖 Generated with Claude Code

The turn-start crash-resilience persist in build_turn_context calls
_apply_persist_user_message_override on the same messages list the API
request is later built from. When the ACP adapter sends a multimodal
prompt (text + image parts) it passes a text-only persist_user_message,
so the override replaced the content-part list with a plain string
before the first provider call — every image content block was dropped
end-to-end, regardless of model vision support.

Skip the override when the live content is a content-part list. The
synthetic-prefix cleanup the override exists for only applies to text
turns (voice prefix, ACP steering), and image redaction for the session
DB already happens in _flush_messages_to_session_db.

Fixes NousResearch#44242

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@alt-glitch alt-glitch added type/bug Something isn't working comp/agent Core agent loop, run_agent.py, prompt builder tool/vision Vision analysis and image generation P2 Medium — degraded but workaround exists duplicate This issue or pull request already exists labels Jun 11, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Duplicate of #44247 — both guard _apply_persist_user_message_override against clobbering multimodal (list) content; #44247 lands the same approach first. Consolidating on the earlier PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent loop, run_agent.py, prompt builder duplicate This issue or pull request already exists P2 Medium — degraded but workaround exists tool/vision Vision analysis and image generation type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ACP image content blocks dropped before API call (persist_user_message override clobbers multimodal content)

2 participants