Skip to content

Commit eef59ce

Browse files
committed
test: add coverage for single tool_result and unexpected role paths
Add two tests to improve patch coverage: - SingleToolResultNotCoalesced: verifies a single tool_result message (without consecutive ones) is handled correctly and not coalesced with a follow-up plain text user message. - UnexpectedRole: verifies that an unexpected message role after system message promotion returns an error. Signed-off-by: liuhy <liuhongyu@apache.org>
1 parent 9579aae commit eef59ce

1 file changed

Lines changed: 110 additions & 0 deletions

File tree

internal/translator/anthropic_awsbedrock_test.go

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
11841294
func TestAnthropicToAWSBedrockTranslator_ResponseBody_NonStreamingToolUseAndReasoning(t *testing.T) {
11851295
translator := NewAnthropicToAWSBedrockTranslator("")
11861296
req := &anthropicschema.MessagesRequest{

0 commit comments

Comments
 (0)