diff --git a/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/main/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverter.java b/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/main/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverter.java index 4ca629ed45..a20e8fa662 100644 --- a/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/main/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverter.java +++ b/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/main/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverter.java @@ -53,13 +53,13 @@ * * *

Important Conversion Behaviors: *

@@ -88,6 +88,7 @@ public List convertMessages(List msgs) { for (Msg msg : msgs) { List parts = new ArrayList<>(); + List toolResultParts = new ArrayList<>(); for (ContentBlock block : msg.getContent()) { if (block instanceof TextBlock tb) { @@ -137,7 +138,7 @@ public List convertMessages(List msgs) { parts.add(partBuilder.build()); } else if (block instanceof ToolResultBlock trb) { - // IMPORTANT: Tool result as independent Content with "user" role + // Tool results from the same message share one user Content. String textOutput = convertToolResultToString(trb.getOutput()); // Create response map with "output" key @@ -154,14 +155,7 @@ public List convertMessages(List msgs) { Part functionResponsePart = Part.builder().functionResponse(functionResponse).build(); - Content toolResultContent = - Content.builder() - .role("user") - .parts(List.of(functionResponsePart)) - .build(); - - result.add(toolResultContent); - // Skip adding to current message parts + toolResultParts.add(functionResponsePart); continue; } else if (block instanceof ImageBlock ib) { @@ -190,6 +184,12 @@ public List convertMessages(List msgs) { } } + if (!toolResultParts.isEmpty()) { + Content toolResultContent = + Content.builder().role("user").parts(toolResultParts).build(); + result.add(toolResultContent); + } + // Add message if there are parts if (!parts.isEmpty()) { String role = convertRole(msg.getRole()); diff --git a/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/test/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverterTest.java b/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/test/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverterTest.java index 6cad792f02..2b33991964 100644 --- a/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/test/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverterTest.java +++ b/agentscope-extensions/agentscope-extensions-model/agentscope-extensions-model-gemini/src/test/java/io/agentscope/extensions/model/gemini/formatter/GeminiMessageConverterTest.java @@ -223,6 +223,38 @@ void testConvertToolResultBlock() { assertEquals("Result text", part.functionResponse().get().response().get().get("output")); } + @Test + @DisplayName("Should group tool results from one message into one user Content") + void testConvertMultipleToolResultBlocks() { + ToolResultBlock firstResult = + ToolResultBlock.builder() + .id("call_123") + .name("search") + .output(List.of(TextBlock.builder().text("First result").build())) + .build(); + ToolResultBlock secondResult = + ToolResultBlock.builder() + .id("call_456") + .name("lookup") + .output(List.of(TextBlock.builder().text("Second result").build())) + .build(); + Msg msg = + Msg.builder() + .name("system") + .content(List.of(firstResult, secondResult)) + .role(MsgRole.TOOL) + .build(); + + List result = converter.convertMessages(List.of(msg)); + + assertEquals(1, result.size()); + Content content = result.get(0); + assertEquals("user", content.role().get()); + assertEquals(2, content.parts().get().size()); + assertEquals("call_123", content.parts().get().get(0).functionResponse().get().id().get()); + assertEquals("call_456", content.parts().get().get(1).functionResponse().get().id().get()); + } + @Test @DisplayName("Should format tool result with single output") void testToolResultSingleOutput() {