Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@
*
* <p><b>Event Mapping:</b>
* <ul>
* <li>AgentScope REASONING events → AG-UI TEXT_MESSAGE_* events (for TextBlock)</li>
* <li>AgentScope REASONING events → AG-UI REASONING_* events (for ThinkingBlock, when enabled)</li>
* <li>AgentScope REASONING/SUMMARY events → AG-UI TEXT_MESSAGE_* events (for TextBlock)</li>
* <li>AgentScope REASONING/SUMMARY events → AG-UI REASONING_* events (for
* ThinkingBlock, when enabled)</li>
* <li>AgentScope TOOL_RESULT events → AG-UI TOOL_CALL_END events</li>
* <li>ToolUseBlock content → AG-UI TOOL_CALL_START events</li>
* </ul>
Expand Down Expand Up @@ -136,8 +137,8 @@ private List<AguiEvent> convertEvent(Event event, EventConversionState state) {
Msg msg = event.getMessage();
EventType type = event.getType();

if (type == EventType.REASONING) {
// Handle reasoning events - convert to text messages and tool calls
if (type == EventType.REASONING || type == EventType.SUMMARY) {
// Handle reasoning/summary events - convert to text messages and tool calls
for (ContentBlock block : msg.getContent()) {
if (block instanceof TextBlock textBlock) {
String text = textBlock.getText();
Expand Down Expand Up @@ -324,14 +325,14 @@ private String extractToolResultText(ToolResultBlock toolResult) {
StringBuilder sb = new StringBuilder();
for (ContentBlock output : toolResult.getOutput()) {
if (output instanceof TextBlock textBlock) {
if (sb.length() > 0) {
if (!sb.isEmpty()) {
sb.append("\n");
}
sb.append(textBlock.getText());
}
}

return sb.length() > 0 ? sb.toString() : null;
return !sb.isEmpty() ? sb.toString() : null;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,114 @@ void testRunWithStreamingTextEvents() {
assertEquals(1, startCount, "Should have only 1 start event for same message ID");
}

@Test
void testRunWithSummaryEventUsesTextMessages() {
Msg summaryChunk =
Msg.builder()
.id("msg-summary")
.role(MsgRole.ASSISTANT)
.content(
TextBlock.builder()
.text("Here is the conversation summary.")
.build())
.build();

Msg summaryFinal =
Msg.builder()
.id("msg-summary")
.role(MsgRole.ASSISTANT)
.content(
TextBlock.builder()
.text("Here is the conversation summary.")
.build())
.build();

Event summaryChunkEvent = new Event(EventType.SUMMARY, summaryChunk, false);
Event summaryFinalEvent = new Event(EventType.SUMMARY, summaryFinal, true);

when(mockAgent.stream(anyList(), any(StreamOptions.class)))
.thenReturn(Flux.just(summaryChunkEvent, summaryFinalEvent));

RunAgentInput input =
RunAgentInput.builder()
.threadId("thread-1")
.runId("run-1")
.messages(List.of(AguiMessage.userMessage("msg-1", "Hello")))
.build();

List<AguiEvent> events = adapter.run(input).collectList().block();

assertNotNull(events);

AguiEvent.TextMessageContent summaryContent =
events.stream()
.filter(e -> e instanceof AguiEvent.TextMessageContent)
.map(e -> (AguiEvent.TextMessageContent) e)
.findFirst()
.orElse(null);

assertNotNull(summaryContent, "Should convert SUMMARY to TextMessageContent");
assertEquals("msg-summary", summaryContent.messageId());
assertEquals("Here is the conversation summary.", summaryContent.delta());

long textEndCount =
events.stream().filter(e -> e instanceof AguiEvent.TextMessageEnd).count();
assertEquals(1, textEndCount, "Should close the summary text message exactly once");
}

@Test
void testRunWithStreamingSummaryEvents() {
Msg summaryChunk1 =
Msg.builder()
.id("msg-summary")
.role(MsgRole.ASSISTANT)
.content(TextBlock.builder().text("First part. ").build())
.build();

Msg summaryChunk2 =
Msg.builder()
.id("msg-summary")
.role(MsgRole.ASSISTANT)
.content(TextBlock.builder().text("Second part.").build())
.build();

Msg summaryFinal =
Msg.builder()
.id("msg-summary")
.role(MsgRole.ASSISTANT)
.content(TextBlock.builder().text("First part. Second part.").build())
.build();

Event event1 = new Event(EventType.SUMMARY, summaryChunk1, false);
Event event2 = new Event(EventType.SUMMARY, summaryChunk2, false);
Event event3 = new Event(EventType.SUMMARY, summaryFinal, true);

when(mockAgent.stream(anyList(), any(StreamOptions.class)))
.thenReturn(Flux.just(event1, event2, event3));

RunAgentInput input =
RunAgentInput.builder()
.threadId("thread-1")
.runId("run-1")
.messages(List.of(AguiMessage.userMessage("msg-1", "Hello")))
.build();

List<AguiEvent> events = adapter.run(input).collectList().block();

assertNotNull(events);

long contentCount =
events.stream().filter(e -> e instanceof AguiEvent.TextMessageContent).count();
assertEquals(2, contentCount, "Should stream summary chunks as text deltas");

long startCount =
events.stream().filter(e -> e instanceof AguiEvent.TextMessageStart).count();
assertEquals(1, startCount, "Should only start the summary message once");

long endCount = events.stream().filter(e -> e instanceof AguiEvent.TextMessageEnd).count();
assertEquals(1, endCount, "Should only end the summary message once");
}

@Test
void testRunWithToolCallEvent() {
Msg toolCallMsg =
Expand Down
Loading