fix(anthropic): preserve provider content blocks on assistant replay (refs #298)#392
Merged
pushpak1300 merged 5 commits intoMay 4, 2026
Merged
Conversation
This was referenced Apr 13, 2026
Member
|
can you fix the merge conflict ? |
ae98298 to
736a434
Compare
Contributor
Author
|
done |
Anthropic's Messages API expects the original ordered content-block
array on multi-turn replay. `mapAssistantMessage()` rebuilt assistant
content from text + tool_use only, dropping `server_tool_use`,
`server_tool_result`, `thinking`, and `redacted_thinking` blocks — so
conversations using advisor, web_search, web_fetch, code_execution, or
extended thinking broke when assistant history was replayed through the
mapper.
Carry the raw ordered blocks on AssistantMessage via a new
`contentBlocks` property. The Anthropic non-streaming parser now
populates it, and `mapAssistantMessage` replays it verbatim (running
through `ensureToolInputIsObject` so empty `input` survives as `{}`).
When `contentBlocks` is empty, the existing text + tool_calls rebuild
is unchanged — backward-compat preserved.
Scope: in-memory AssistantMessage replay only. Persistence-backed
conversations via `DatabaseConversationStore` need a matching schema +
rehydration change, tracked separately in laravel#380. Streaming replay
already uses raw response content directly and is unaffected.
References laravel#298.
Reframe the docblock to make intent explicit: contentBlocks is a replay carrier for provider-native blocks (populated by the SDK's own parser), not a general-purpose user-authored schema. Preempts review concerns about public API surface.
736a434 to
2bb0da3
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hit this integrating advisor — every multi-turn advisor conversation 400s because the
advisor_tool_resultblock drops on replay.MapsMessages::mapAssistantMessage()rebuilds assistant content fromtext+tool_callsonly. On replay that drops Anthropic provider blocks likeserver_tool_use,server_tool_result,thinking, andredacted_thinking. In multi-turn conversations that used server tools, the next request can fail with400 invalid_request_errorbecause the assistant history no longer matches what Anthropic expects. This is the in-memory replay side of #298.This change adds a
contentBlocksproperty toAssistantMessageand uses it verbatim inmapAssistantMessage()when present, instead of rebuilding fromtext+tool_calls. The non-streaming parser now passes the raw ordered content array intoAssistantMessage. IfcontentBlocksis empty, the existing path is unchanged, so current behavior and older cached/unserialized messages still fall back to the old rebuild logic.Scope is limited to in-memory
AssistantMessagereplay.DatabaseConversationStorestill rehydrates assistant messages fromtext+tool_calls, so persisted conversations are unchanged here; that needs schema work and is already tracked in #380. Streaming is also unchanged: same-request replay already uses the raw response content directly and does not go throughmapAssistantMessage().Tests cover the verbatim mapping path, parser population of
contentBlocks, round-tripping a parsed assistant message back throughmapMessages(), and the fallback behavior whencontentBlocksis absent. Anthropic tests are green. Related: #380 for persistence, #301 for adjacent reasoning-data loss, and #349 for the TextOrchestrator refactor this avoids touching.