@@ -1181,6 +1181,116 @@ func TestAnthropicToAWSBedrockTranslator_RequestBody_ToolResultMessagesWithSyste
11811181 assert .Contains (t , * bedrockReq .System [0 ].Text , "Always be concise." )
11821182}
11831183
1184+ func TestAnthropicToAWSBedrockTranslator_RequestBody_SingleToolResultNotCoalesced (t * testing.T ) {
1185+ // Verify that a single tool_result message (without a consecutive one) is NOT coalesced
1186+ // but still goes through the tool result path (not convertUserMessage).
1187+ translator := NewAnthropicToAWSBedrockTranslator ("" )
1188+ req := & anthropicschema.MessagesRequest {
1189+ Model : "test-model" ,
1190+ MaxTokens : 100 ,
1191+ Tools : []anthropicschema.ToolUnion {
1192+ {Tool : & anthropicschema.Tool {
1193+ Type : "custom" ,
1194+ Name : "get_weather" ,
1195+ Description : "Get weather" ,
1196+ InputSchema : anthropicschema.ToolInputSchema {Type : "object" },
1197+ }},
1198+ },
1199+ Messages : []anthropicschema.MessageParam {
1200+ {
1201+ Role : anthropicschema .MessageRoleUser ,
1202+ Content : anthropicschema.MessageContent {Text : "What's the weather?" },
1203+ },
1204+ {
1205+ Role : anthropicschema .MessageRoleAssistant ,
1206+ Content : anthropicschema.MessageContent {
1207+ Array : []anthropicschema.ContentBlockParam {
1208+ {ToolUse : & anthropicschema.ToolUseBlockParam {
1209+ Type : "tool_use" ,
1210+ ID : "tu_abc" ,
1211+ Name : "get_weather" ,
1212+ Input : map [string ]any {"city" : "NYC" },
1213+ }},
1214+ },
1215+ },
1216+ },
1217+ // Single tool result — no consecutive tool result to coalesce with.
1218+ {
1219+ Role : anthropicschema .MessageRoleUser ,
1220+ Content : anthropicschema.MessageContent {
1221+ Array : []anthropicschema.ContentBlockParam {
1222+ {ToolResult : & anthropicschema.ToolResultBlockParam {
1223+ Type : "tool_result" ,
1224+ ToolUseID : "tu_abc" ,
1225+ Content : & anthropicschema.ToolResultContent {Text : "72°F and sunny" },
1226+ }},
1227+ },
1228+ },
1229+ },
1230+ // Follow-up user text message — should NOT be coalesced with tool result.
1231+ {
1232+ Role : anthropicschema .MessageRoleUser ,
1233+ Content : anthropicschema.MessageContent {Text : "Thanks!" },
1234+ },
1235+ },
1236+ }
1237+ rawBody , err := json .Marshal (req )
1238+ require .NoError (t , err )
1239+
1240+ _ , body , err := translator .RequestBody (rawBody , req , false )
1241+ require .NoError (t , err )
1242+
1243+ var bedrockReq awsbedrock.ConverseInput
1244+ err = json .Unmarshal (body , & bedrockReq )
1245+ require .NoError (t , err )
1246+
1247+ // 4 messages: user, assistant, user(tool_result), user(text)
1248+ require .Len (t , bedrockReq .Messages , 4 )
1249+
1250+ // Third message: tool result (not coalesced).
1251+ toolResultMsg := bedrockReq .Messages [2 ]
1252+ assert .Equal (t , awsbedrock .ConversationRoleUser , toolResultMsg .Role )
1253+ require .Len (t , toolResultMsg .Content , 1 )
1254+ require .NotNil (t , toolResultMsg .Content [0 ].ToolResult )
1255+ assert .Equal (t , "tu_abc" , * toolResultMsg .Content [0 ].ToolResult .ToolUseID )
1256+
1257+ // Fourth message: plain text (not coalesced with tool result).
1258+ textMsg := bedrockReq .Messages [3 ]
1259+ assert .Equal (t , awsbedrock .ConversationRoleUser , textMsg .Role )
1260+ require .Len (t , textMsg .Content , 1 )
1261+ assert .NotNil (t , textMsg .Content [0 ].Text )
1262+ assert .Equal (t , "Thanks!" , * textMsg .Content [0 ].Text )
1263+ }
1264+
1265+ func TestAnthropicToAWSBedrockTranslator_RequestBody_UnexpectedRole (t * testing.T ) {
1266+ // Verify that an unexpected role returns an error.
1267+ translator := NewAnthropicToAWSBedrockTranslator ("" )
1268+ req := & anthropicschema.MessagesRequest {
1269+ Model : "test-model" ,
1270+ MaxTokens : 100 ,
1271+ Messages : []anthropicschema.MessageParam {
1272+ {
1273+ Role : anthropicschema .MessageRoleUser ,
1274+ Content : anthropicschema.MessageContent {Text : "Hello" },
1275+ },
1276+ {
1277+ Role : "system" , // Will be promoted to system param.
1278+ Content : anthropicschema.MessageContent {Text : "You are helpful." },
1279+ },
1280+ {
1281+ Role : "invalid_role" ,
1282+ Content : anthropicschema.MessageContent {Text : "This should fail" },
1283+ },
1284+ },
1285+ }
1286+ rawBody , err := json .Marshal (req )
1287+ require .NoError (t , err )
1288+
1289+ _ , _ , err = translator .RequestBody (rawBody , req , false )
1290+ require .Error (t , err )
1291+ assert .Contains (t , err .Error (), "unexpected role: invalid_role" )
1292+ }
1293+
11841294func TestAnthropicToAWSBedrockTranslator_ResponseBody_NonStreamingToolUseAndReasoning (t * testing.T ) {
11851295 translator := NewAnthropicToAWSBedrockTranslator ("" )
11861296 req := & anthropicschema.MessagesRequest {
0 commit comments