@@ -27,14 +27,15 @@ interface BedrockMessageContent {
2727/**
2828 * Convert Anthropic messages to Bedrock Converse format
2929 * @param anthropicMessages Messages in Anthropic format
30- * @param options.preserveReasoning Replay reasoning/thinking blocks as `reasoningContent`.
30+ * @param options.preserveReasoning Replay reasoning/thinking blocks as `reasoningContent` while a tool loop
31+ * continues; reasoning followed by a new user message is dropped.
3132 * Otherwise they are dropped, matching Task's stripping for models without `preserveReasoning`.
3233 */
3334export function convertToBedrockConverseMessages (
3435 anthropicMessages : Anthropic . Messages . MessageParam [ ] ,
3536 { preserveReasoning = false } : { preserveReasoning ?: boolean } = { } ,
3637) : Message [ ] {
37- return anthropicMessages . map ( ( anthropicMessage ) => {
38+ return anthropicMessages . map ( ( anthropicMessage , index ) => {
3839 // Map Anthropic roles to Bedrock roles
3940 const role : ConversationRole = anthropicMessage . role === "assistant" ? "assistant" : "user"
4041
@@ -52,12 +53,19 @@ export function convertToBedrockConverseMessages(
5253 // Signed thinking blocks (e.g. from MiniMax) bypass Task's reasoning filter, so they can reach
5354 // any Bedrock model after a provider switch. Unsigned reasoning is only safe for models that
5455 // opt in; Claude would receive thinking it cannot verify.
55- const blocks = preserveReasoning
56- ? anthropicMessage . content
57- : anthropicMessage . content . filter ( ( block ) => {
58- const type = ( block as { type : string } ) . type
59- return type !== "reasoning" && type !== "thinking"
60- } )
56+ // Reasoning continuity only spans a tool loop: a following new user message ends it.
57+ const next = anthropicMessages [ index + 1 ]
58+ const endsAtNewUserMessage =
59+ next ?. role === "user" &&
60+ ( typeof next . content === "string" ||
61+ ! next . content . some ( ( block ) => ( block as { type : string } ) . type === "tool_result" ) )
62+ const blocks =
63+ preserveReasoning && ! endsAtNewUserMessage
64+ ? anthropicMessage . content
65+ : anthropicMessage . content . filter ( ( block ) => {
66+ const type = ( block as { type : string } ) . type
67+ return type !== "reasoning" && type !== "thinking"
68+ } )
6169
6270 // Process complex content types
6371 const content = blocks . map ( ( block ) => {
0 commit comments