@@ -133,11 +133,20 @@ func ConformanceTests(t *testing.T, props map[string]string, conv conversation.C
133133 resp , err := conv .Converse (ctx , req )
134134
135135 require .NoError (t , err )
136- assert .Len (t , resp .Outputs , 1 )
137- assert .NotEmpty (t , resp .Outputs [0 ].Choices [0 ].Message .Content )
138- // anthropic responds with end_turn but other llm providers return with stop
139- assert .True (t , slices .Contains ([]string {"stop" , "end_turn" }, resp .Outputs [0 ].StopReason ))
140- assert .Empty (t , resp .Outputs [0 ].Choices [0 ].Message .ToolCallRequest )
136+ // Echo component returns one output per message, other components return one output
137+ if component == "echo" {
138+ assert .Len (t , resp .Outputs , 2 )
139+ // Check the last output - system message
140+ assert .NotEmpty (t , resp .Outputs [1 ].Choices [0 ].Message .Content )
141+ assert .True (t , slices .Contains ([]string {"stop" , "end_turn" }, resp .Outputs [1 ].StopReason ))
142+ assert .Empty (t , resp .Outputs [1 ].Choices [0 ].Message .ToolCallRequest )
143+ } else {
144+ assert .Len (t , resp .Outputs , 1 )
145+ assert .NotEmpty (t , resp .Outputs [0 ].Choices [0 ].Message .Content )
146+ // anthropic responds with end_turn but other llm providers return with stop
147+ assert .True (t , slices .Contains ([]string {"stop" , "end_turn" }, resp .Outputs [0 ].StopReason ))
148+ assert .Empty (t , resp .Outputs [0 ].Choices [0 ].Message .ToolCallRequest )
149+ }
141150 })
142151 t .Run ("test assistant message type" , func (t * testing.T ) {
143152 ctx , cancel := context .WithTimeout (t .Context (), 25 * time .Second )
@@ -224,13 +233,26 @@ func ConformanceTests(t *testing.T, props map[string]string, conv conversation.C
224233 resp , err := conv .Converse (ctx , req )
225234
226235 require .NoError (t , err )
227- assert .Len (t , resp .Outputs , 1 )
228- assert .NotEmpty (t , resp .Outputs [0 ].Choices [0 ].Message .Content )
229- // anthropic responds with end_turn but other llm providers return with stop
230- assert .True (t , slices .Contains ([]string {"stop" , "end_turn" }, resp .Outputs [0 ].StopReason ))
231- if resp .Outputs [0 ].Choices [0 ].Message .ToolCallRequest != nil && len (* resp .Outputs [0 ].Choices [0 ].Message .ToolCallRequest ) > 0 {
232- assert .NotEmpty (t , resp .Outputs [0 ].Choices [0 ].Message .ToolCallRequest )
233- require .JSONEq (t , `{"test": "value"}` , (* resp .Outputs [0 ].Choices [0 ].Message .ToolCallRequest )[0 ].FunctionCall .Arguments )
236+ // Echo component returns one output per message, other components return one output
237+ if component == "echo" {
238+ assert .Len (t , resp .Outputs , 4 )
239+ // Check the last output - human message
240+ assert .NotEmpty (t , resp .Outputs [3 ].Choices [0 ].Message .Content )
241+ assert .True (t , slices .Contains ([]string {"stop" , "end_turn" }, resp .Outputs [3 ].StopReason ))
242+ // Check the tool call output - second output
243+ if resp .Outputs [1 ].Choices [0 ].Message .ToolCallRequest != nil && len (* resp .Outputs [1 ].Choices [0 ].Message .ToolCallRequest ) > 0 {
244+ assert .NotEmpty (t , resp .Outputs [1 ].Choices [0 ].Message .ToolCallRequest )
245+ require .JSONEq (t , `{"test": "value"}` , (* resp .Outputs [1 ].Choices [0 ].Message .ToolCallRequest )[0 ].FunctionCall .Arguments )
246+ }
247+ } else {
248+ assert .Len (t , resp .Outputs , 1 )
249+ assert .NotEmpty (t , resp .Outputs [0 ].Choices [0 ].Message .Content )
250+ // anthropic responds with end_turn but other llm providers return with stop
251+ assert .True (t , slices .Contains ([]string {"stop" , "end_turn" }, resp .Outputs [0 ].StopReason ))
252+ if resp .Outputs [0 ].Choices [0 ].Message .ToolCallRequest != nil && len (* resp .Outputs [0 ].Choices [0 ].Message .ToolCallRequest ) > 0 {
253+ assert .NotEmpty (t , resp .Outputs [0 ].Choices [0 ].Message .ToolCallRequest )
254+ require .JSONEq (t , `{"test": "value"}` , (* resp .Outputs [0 ].Choices [0 ].Message .ToolCallRequest )[0 ].FunctionCall .Arguments )
255+ }
234256 }
235257 })
236258
@@ -306,14 +328,14 @@ func ConformanceTests(t *testing.T, props map[string]string, conv conversation.C
306328 if resp .Outputs [0 ].Choices [0 ].Message .ToolCallRequest != nil {
307329 assert .GreaterOrEqual (t , len (* resp .Outputs [0 ].Choices [0 ].Message .ToolCallRequest ), 1 )
308330
309- var toolCall * llms.ToolCall
331+ var toolCall llms.ToolCall
310332 for i := range * resp .Outputs [0 ].Choices [0 ].Message .ToolCallRequest {
311333 if (* resp .Outputs [0 ].Choices [0 ].Message .ToolCallRequest )[i ].FunctionCall .Name == "get_project_name" {
312- toolCall = & (* resp .Outputs [0 ].Choices [0 ].Message .ToolCallRequest )[i ]
334+ toolCall = (* resp .Outputs [0 ].Choices [0 ].Message .ToolCallRequest )[i ]
313335 break
314336 }
315337 }
316- require .NotNil (t , toolCall )
338+ require .NotEmpty (t , toolCall . ID )
317339 assert .Equal (t , "get_project_name" , toolCall .FunctionCall .Name )
318340 assert .Contains (t , toolCall .FunctionCall .Arguments , "repo_link" )
319341
@@ -348,7 +370,7 @@ func ConformanceTests(t *testing.T, props map[string]string, conv conversation.C
348370 responseMessages = append (responseMessages ,
349371 llms.MessageContent {
350372 Role : llms .ChatMessageTypeAI ,
351- Parts : []llms.ContentPart {mistral .CreateToolCallPart (toolCall )},
373+ Parts : []llms.ContentPart {mistral .CreateToolCallPart (& toolCall )},
352374 },
353375 mistral .CreateToolResponseMessage (toolResponse ),
354376 )
@@ -413,24 +435,26 @@ func ConformanceTests(t *testing.T, props map[string]string, conv conversation.C
413435 require .NoError (t , err )
414436
415437 // handle potentially multiple outputs from different llm providers
416- var toolCall * llms.ToolCall
438+ var toolCall llms.ToolCall
439+ found := false
417440 for _ , output := range resp1 .Outputs {
418441 if output .Choices [0 ].Message .ToolCallRequest != nil {
419442 // find the tool call with the expected function name
420443 for i := range * output .Choices [0 ].Message .ToolCallRequest {
421444 if (* output .Choices [0 ].Message .ToolCallRequest )[i ].FunctionCall .Name == "retrieve_payment_status" {
422- toolCall = & (* output .Choices [0 ].Message .ToolCallRequest )[i ]
445+ toolCall = (* output .Choices [0 ].Message .ToolCallRequest )[i ]
446+ found = true
423447 break
424448 }
425449 }
426- if toolCall != nil {
450+ if found {
427451 break
428452 }
429453 }
430454 }
431455
432456 // check if we got a tool call request
433- if toolCall != nil {
457+ if found {
434458 assert .Equal (t , "retrieve_payment_status" , toolCall .FunctionCall .Name )
435459 assert .Contains (t , toolCall .FunctionCall .Arguments , "T1001" )
436460
@@ -451,7 +475,7 @@ func ConformanceTests(t *testing.T, props map[string]string, conv conversation.C
451475 },
452476 {
453477 Role : llms .ChatMessageTypeAI ,
454- Parts : []llms.ContentPart {* toolCall },
478+ Parts : []llms.ContentPart {toolCall },
455479 },
456480 {
457481 Role : llms .ChatMessageTypeTool ,
@@ -470,7 +494,7 @@ func ConformanceTests(t *testing.T, props map[string]string, conv conversation.C
470494 },
471495 {
472496 Role : llms .ChatMessageTypeAI ,
473- Parts : []llms.ContentPart {mistral .CreateToolCallPart (toolCall )},
497+ Parts : []llms.ContentPart {mistral .CreateToolCallPart (& toolCall )},
474498 },
475499 mistral .CreateToolResponseMessage (toolResponse ),
476500 }
0 commit comments