Skip to content

Commit 984a2f4

Browse files
committed
test(autocontext): cover current-round tool compression branches
1 parent 58cf09a commit 984a2f4

1 file changed

Lines changed: 129 additions & 0 deletions

File tree

  • agentscope-extensions/agentscope-extensions-autocontext-memory/src/test/java/io/agentscope/core/memory/autocontext

agentscope-extensions/agentscope-extensions-autocontext-memory/src/test/java/io/agentscope/core/memory/autocontext/AutoContextMemoryTest.java

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,135 @@ void testCurrentRoundCompressionPreservesToolPairStructure() {
806806
"Compressed tool message should preserve both tool results");
807807
}
808808

809+
@Test
810+
@DisplayName(
811+
"Should keep plain current round compression as a single summary message when no"
812+
+ " tool interaction exists")
813+
void testMergeAndCompressCurrentRoundMessagesWithoutToolInteraction()
814+
throws ReflectiveOperationException {
815+
TestModel model = new TestModel("Plain current round summary");
816+
AutoContextMemory mem = new AutoContextMemory(config, model);
817+
818+
List<Msg> currentRoundMessages =
819+
new ArrayList<>(
820+
List.of(
821+
createTextMessage("User asks a plain question", MsgRole.USER),
822+
createTextMessage(
823+
"Assistant answers without tools", MsgRole.ASSISTANT)));
824+
825+
Method method =
826+
AutoContextMemory.class.getDeclaredMethod(
827+
"mergeAndCompressCurrentRoundMessages", List.class);
828+
method.setAccessible(true);
829+
830+
@SuppressWarnings("unchecked")
831+
List<Msg> compressedMessages = (List<Msg>) method.invoke(mem, currentRoundMessages);
832+
833+
assertNotNull(compressedMessages, "Compression should return a summary message list");
834+
assertEquals(
835+
1,
836+
compressedMessages.size(),
837+
"Plain current round compression should stay as a single summary message");
838+
assertEquals(
839+
MsgRole.ASSISTANT,
840+
compressedMessages.get(0).getRole(),
841+
"Summary message should remain an assistant message");
842+
assertTrue(
843+
compressedMessages.get(0).getTextContent().contains("Plain current round summary"),
844+
"Summary text should come from the compression model");
845+
846+
assertEquals(
847+
1, mem.getOffloadContext().size(), "Original messages should still be offloaded");
848+
assertEquals(
849+
2,
850+
mem.getOffloadContext().values().iterator().next().size(),
851+
"Offload context should retain the original current-round messages");
852+
}
853+
854+
@Test
855+
@DisplayName(
856+
"Should fall back to summary text when tool-aware compression only sees tool results")
857+
void testBuildToolAwareCurrentRoundCompressionWithToolResultsOnly()
858+
throws ReflectiveOperationException {
859+
AutoContextMemory mem = new AutoContextMemory(config, testModel);
860+
List<Msg> toolOnlyMessages =
861+
List.of(
862+
Msg.builder()
863+
.role(MsgRole.TOOL)
864+
.name("tool")
865+
.content(
866+
ToolResultBlock.of(
867+
"call_only",
868+
null,
869+
TextBlock.builder().text("raw tool output").build(),
870+
Map.of("source", "tool-only-test")))
871+
.build());
872+
Msg summaryMsg =
873+
Msg.builder()
874+
.role(MsgRole.ASSISTANT)
875+
.name("assistant")
876+
.content(TextBlock.builder().text("Tool-only summary").build())
877+
.build();
878+
879+
Method method =
880+
AutoContextMemory.class.getDeclaredMethod(
881+
"buildToolAwareCurrentRoundCompression",
882+
List.class,
883+
Msg.class,
884+
String.class);
885+
method.setAccessible(true);
886+
887+
@SuppressWarnings("unchecked")
888+
List<Msg> compressedMessages =
889+
(List<Msg>) method.invoke(mem, toolOnlyMessages, summaryMsg, null);
890+
891+
assertEquals(
892+
2,
893+
compressedMessages.size(),
894+
"Tool-only current round should still emit assistant and tool messages");
895+
896+
Msg assistantMsg = compressedMessages.get(0);
897+
assertEquals(
898+
MsgRole.ASSISTANT,
899+
assistantMsg.getRole(),
900+
"First compressed message should be assistant");
901+
assertEquals(
902+
"Tool-only summary",
903+
assistantMsg.getTextContent(),
904+
"Assistant fallback should keep the summary text when no tool-use blocks exist");
905+
assertFalse(
906+
assistantMsg.hasContentBlocks(ToolUseBlock.class),
907+
"Tool-only fallback should not fabricate ToolUseBlock content");
908+
assertTrue(
909+
assistantMsg.getMetadata().isEmpty(),
910+
"Assistant metadata should stay empty when summary metadata is absent");
911+
912+
Msg toolMsg = compressedMessages.get(1);
913+
assertEquals(
914+
MsgRole.TOOL, toolMsg.getRole(), "Second compressed message should be tool role");
915+
ToolResultBlock resultBlock = toolMsg.getFirstContentBlock(ToolResultBlock.class);
916+
assertNotNull(
917+
resultBlock, "Compressed tool message should preserve ToolResultBlock structure");
918+
assertEquals("call_only", resultBlock.getId(), "Tool result id should be preserved");
919+
assertNull(
920+
resultBlock.getName(), "Null tool names should stay null on the preserved block");
921+
assertEquals(
922+
"Tool result for tool is summarized in the paired assistant compression message.",
923+
resultBlock.getOutput().stream()
924+
.filter(TextBlock.class::isInstance)
925+
.map(TextBlock.class::cast)
926+
.map(TextBlock::getText)
927+
.findFirst()
928+
.orElse(""),
929+
"Placeholder should fall back to the generic tool label without an offload tag");
930+
assertTrue(
931+
toolMsg.getMetadata().containsKey("_compress_meta"),
932+
"Compressed tool message should still include compression metadata wrapper");
933+
assertTrue(
934+
((Map<?, ?>) toolMsg.getMetadata().get("_compress_meta")).isEmpty(),
935+
"Compression metadata should stay empty when no offload uuid is provided");
936+
}
937+
809938
@Test
810939
@DisplayName(
811940
"Should skip tool message compression when token count is below"

0 commit comments

Comments
 (0)