Skip to content

Commit 9a3af0e

Browse files
committed
fix: skip compressed assistant tool calls
1 parent 28ef28a commit 9a3af0e

2 files changed

Lines changed: 109 additions & 0 deletions

File tree

agentscope-core/src/main/java/io/agentscope/core/util/MessageUtils.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import io.agentscope.core.message.MsgRole;
2020
import io.agentscope.core.message.ToolUseBlock;
2121
import java.util.List;
22+
import java.util.Map;
2223
import java.util.Objects;
2324

2425
/**
@@ -30,6 +31,8 @@
3031
*/
3132
public final class MessageUtils {
3233

34+
private static final String COMPRESS_META_KEY = "_compress_meta";
35+
3336
private MessageUtils() {
3437
throw new UnsupportedOperationException("Utility class cannot be instantiated");
3538
}
@@ -53,6 +56,9 @@ public static List<ToolUseBlock> extractRecentToolCalls(List<Msg> messages, Stri
5356
for (int i = messages.size() - 1; i >= 0; i--) {
5457
Msg msg = messages.get(i);
5558
if (msg.getRole() == MsgRole.ASSISTANT && Objects.equals(msg.getName(), agentName)) {
59+
if (isCompressedMessage(msg)) {
60+
continue;
61+
}
5662
List<ToolUseBlock> toolCalls = msg.getContentBlocks(ToolUseBlock.class);
5763
if (!toolCalls.isEmpty()) {
5864
return toolCalls;
@@ -63,4 +69,17 @@ public static List<ToolUseBlock> extractRecentToolCalls(List<Msg> messages, Stri
6369

6470
return List.of();
6571
}
72+
73+
private static boolean isCompressedMessage(Msg msg) {
74+
if (msg == null) {
75+
return false;
76+
}
77+
78+
Map<String, Object> metadata = msg.getMetadata();
79+
if (metadata == null) {
80+
return false;
81+
}
82+
83+
return metadata.get(COMPRESS_META_KEY) instanceof Map;
84+
}
6685
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright 2024-2026 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.agentscope.core.util;
17+
18+
import static org.junit.jupiter.api.Assertions.assertEquals;
19+
import static org.junit.jupiter.api.Assertions.assertFalse;
20+
import static org.junit.jupiter.api.Assertions.assertTrue;
21+
22+
import io.agentscope.core.message.Msg;
23+
import io.agentscope.core.message.MsgRole;
24+
import io.agentscope.core.message.TextBlock;
25+
import io.agentscope.core.message.ToolUseBlock;
26+
import java.util.ArrayList;
27+
import java.util.HashMap;
28+
import java.util.List;
29+
import java.util.Map;
30+
import org.junit.jupiter.api.DisplayName;
31+
import org.junit.jupiter.api.Test;
32+
33+
@DisplayName("MessageUtils Tests")
34+
class MessageUtilsTest {
35+
36+
@Test
37+
@DisplayName("Should skip compressed assistant messages when extracting recent tool calls")
38+
void testExtractRecentToolCallsSkipsCompressedAssistantMessages() {
39+
List<Msg> messages = new ArrayList<>();
40+
messages.add(createAssistantToolUseMessage("real-tool", "real-call"));
41+
messages.add(createCompressedAssistantToolUseMessage("compressed-tool", "compressed-call"));
42+
43+
List<ToolUseBlock> toolCalls = MessageUtils.extractRecentToolCalls(messages, "assistant");
44+
45+
assertEquals(1, toolCalls.size());
46+
assertEquals("real-tool", toolCalls.get(0).getName());
47+
assertEquals("real-call", toolCalls.get(0).getId());
48+
assertFalse(toolCalls.stream().anyMatch(block -> "compressed-call".equals(block.getId())));
49+
}
50+
51+
@Test
52+
@DisplayName("Should return empty list when messages are null or empty")
53+
void testExtractRecentToolCallsWithEmptyInput() {
54+
assertTrue(MessageUtils.extractRecentToolCalls(null, "assistant").isEmpty());
55+
assertTrue(MessageUtils.extractRecentToolCalls(List.of(), "assistant").isEmpty());
56+
}
57+
58+
private Msg createAssistantToolUseMessage(String toolName, String callId) {
59+
return Msg.builder()
60+
.role(MsgRole.ASSISTANT)
61+
.name("assistant")
62+
.content(
63+
List.of(
64+
ToolUseBlock.builder()
65+
.name(toolName)
66+
.id(callId)
67+
.input(new HashMap<>())
68+
.build()))
69+
.build();
70+
}
71+
72+
private Msg createCompressedAssistantToolUseMessage(String toolName, String callId) {
73+
Map<String, Object> metadata = new HashMap<>();
74+
metadata.put("_compress_meta", Map.of("offloaduuid", "uuid-123"));
75+
76+
return Msg.builder()
77+
.role(MsgRole.ASSISTANT)
78+
.name("assistant")
79+
.content(
80+
List.of(
81+
ToolUseBlock.builder()
82+
.name(toolName)
83+
.id(callId)
84+
.input(new HashMap<>())
85+
.build(),
86+
TextBlock.builder().text("Compressed summary").build()))
87+
.metadata(metadata)
88+
.build();
89+
}
90+
}

0 commit comments

Comments
 (0)