@@ -141,10 +141,10 @@ describe("convertToBedrockConverseMessages", () => {
141141 }
142142 } )
143143
144- it ( "converts tool result messages correctly " , ( ) => {
144+ it ( "converts tool result messages to XML text format (default, useNativeTools: false) " , ( ) => {
145145 const messages : Anthropic . Messages . MessageParam [ ] = [
146146 {
147- role : "assistant " ,
147+ role : "user " ,
148148 content : [
149149 {
150150 type : "tool_result" ,
@@ -155,14 +155,50 @@ describe("convertToBedrockConverseMessages", () => {
155155 } ,
156156 ]
157157
158+ // Default behavior (useNativeTools: false) converts tool_result to XML text format
159+ // This fixes the Bedrock error "toolConfig field must be defined when using toolUse and toolResult content blocks"
158160 const result = convertToBedrockConverseMessages ( messages )
159161
160162 if ( ! result [ 0 ] || ! result [ 0 ] . content ) {
161163 expect . fail ( "Expected result to have content" )
162164 return
163165 }
164166
165- expect ( result [ 0 ] . role ) . toBe ( "assistant" )
167+ expect ( result [ 0 ] . role ) . toBe ( "user" )
168+ const textBlock = result [ 0 ] . content [ 0 ] as ContentBlock
169+ if ( "text" in textBlock ) {
170+ expect ( textBlock . text ) . toContain ( "<tool_result>" )
171+ expect ( textBlock . text ) . toContain ( "<tool_use_id>test-id</tool_use_id>" )
172+ expect ( textBlock . text ) . toContain ( "File contents here" )
173+ expect ( textBlock . text ) . toContain ( "</tool_result>" )
174+ } else {
175+ expect . fail ( "Expected text block with XML content not found" )
176+ }
177+ } )
178+
179+ it ( "converts tool result messages to native format (useNativeTools: true)" , ( ) => {
180+ const messages : Anthropic . Messages . MessageParam [ ] = [
181+ {
182+ role : "user" ,
183+ content : [
184+ {
185+ type : "tool_result" ,
186+ tool_use_id : "test-id" ,
187+ content : [ { type : "text" , text : "File contents here" } ] ,
188+ } ,
189+ ] ,
190+ } ,
191+ ]
192+
193+ // With useNativeTools: true, keeps tool_result as native format
194+ const result = convertToBedrockConverseMessages ( messages , { useNativeTools : true } )
195+
196+ if ( ! result [ 0 ] || ! result [ 0 ] . content ) {
197+ expect . fail ( "Expected result to have content" )
198+ return
199+ }
200+
201+ expect ( result [ 0 ] . role ) . toBe ( "user" )
166202 const resultBlock = result [ 0 ] . content [ 0 ] as ContentBlock
167203 if ( "toolResult" in resultBlock && resultBlock . toolResult ) {
168204 const expectedContent : ToolResultContentBlock [ ] = [ { text : "File contents here" } ]
@@ -176,7 +212,7 @@ describe("convertToBedrockConverseMessages", () => {
176212 }
177213 } )
178214
179- it ( "converts tool result messages with string content correctly " , ( ) => {
215+ it ( "converts tool result messages with string content to XML text format (default) " , ( ) => {
180216 const messages : Anthropic . Messages . MessageParam [ ] = [
181217 {
182218 role : "user" ,
@@ -197,6 +233,39 @@ describe("convertToBedrockConverseMessages", () => {
197233 return
198234 }
199235
236+ expect ( result [ 0 ] . role ) . toBe ( "user" )
237+ const textBlock = result [ 0 ] . content [ 0 ] as ContentBlock
238+ if ( "text" in textBlock ) {
239+ expect ( textBlock . text ) . toContain ( "<tool_result>" )
240+ expect ( textBlock . text ) . toContain ( "<tool_use_id>test-id</tool_use_id>" )
241+ expect ( textBlock . text ) . toContain ( "File: test.txt" )
242+ expect ( textBlock . text ) . toContain ( "Hello World" )
243+ } else {
244+ expect . fail ( "Expected text block with XML content not found" )
245+ }
246+ } )
247+
248+ it ( "converts tool result messages with string content to native format (useNativeTools: true)" , ( ) => {
249+ const messages : Anthropic . Messages . MessageParam [ ] = [
250+ {
251+ role : "user" ,
252+ content : [
253+ {
254+ type : "tool_result" ,
255+ tool_use_id : "test-id" ,
256+ content : "File: test.txt\nLines 1-5:\nHello World" ,
257+ } as any , // Anthropic types don't allow string content but runtime can have it
258+ ] ,
259+ } ,
260+ ]
261+
262+ const result = convertToBedrockConverseMessages ( messages , { useNativeTools : true } )
263+
264+ if ( ! result [ 0 ] || ! result [ 0 ] . content ) {
265+ expect . fail ( "Expected result to have content" )
266+ return
267+ }
268+
200269 expect ( result [ 0 ] . role ) . toBe ( "user" )
201270 const resultBlock = result [ 0 ] . content [ 0 ] as ContentBlock
202271 if ( "toolResult" in resultBlock && resultBlock . toolResult ) {
@@ -210,6 +279,56 @@ describe("convertToBedrockConverseMessages", () => {
210279 }
211280 } )
212281
282+ it ( "converts both tool_use and tool_result consistently when native tools disabled" , ( ) => {
283+ // This test ensures tool_use AND tool_result are both converted to XML text
284+ // when useNativeTools is false, preventing Bedrock toolConfig errors
285+ const messages : Anthropic . Messages . MessageParam [ ] = [
286+ {
287+ role : "assistant" ,
288+ content : [
289+ {
290+ type : "tool_use" ,
291+ id : "call-123" ,
292+ name : "read_file" ,
293+ input : { path : "test.txt" } ,
294+ } ,
295+ ] ,
296+ } ,
297+ {
298+ role : "user" ,
299+ content : [
300+ {
301+ type : "tool_result" ,
302+ tool_use_id : "call-123" ,
303+ content : "File contents here" ,
304+ } as any ,
305+ ] ,
306+ } ,
307+ ]
308+
309+ const result = convertToBedrockConverseMessages ( messages ) // default useNativeTools: false
310+
311+ // Both should be text blocks, not native toolUse/toolResult
312+ const assistantContent = result [ 0 ] ?. content ?. [ 0 ] as ContentBlock
313+ const userContent = result [ 1 ] ?. content ?. [ 0 ] as ContentBlock
314+
315+ // tool_use should be XML text
316+ expect ( "text" in assistantContent ) . toBe ( true )
317+ if ( "text" in assistantContent ) {
318+ expect ( assistantContent . text ) . toContain ( "<tool_use>" )
319+ }
320+
321+ // tool_result should also be XML text (this is what the fix addresses)
322+ expect ( "text" in userContent ) . toBe ( true )
323+ if ( "text" in userContent ) {
324+ expect ( userContent . text ) . toContain ( "<tool_result>" )
325+ }
326+
327+ // Neither should have native format
328+ expect ( "toolUse" in assistantContent ) . toBe ( false )
329+ expect ( "toolResult" in userContent ) . toBe ( false )
330+ } )
331+
213332 it ( "handles text content correctly" , ( ) => {
214333 const messages : Anthropic . Messages . MessageParam [ ] = [
215334 {
0 commit comments