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 @@ -197,13 +197,28 @@ private static Optional<Event> handleTaskUpdate(
}
if (updateEvent instanceof TaskStatusUpdateEvent statusEvent) {
var status = statusEvent.getStatus();
return Optional.ofNullable(status.message())
.map(
value ->
messageToEvent(
value,
context,
PENDING_STATES.contains(event.getTask().getStatus().state())));
var taskState = event.getTask().getStatus().state();

Optional<Event> messageEvent =
Optional.ofNullable(status.message())
.map(
value ->
messageToEvent(
value,
context,
PENDING_STATES.contains(taskState),
taskState == TaskState.FAILED));

if (statusEvent.isFinal()) {
return messageEvent
.map(Event::toBuilder)
.or(() -> Optional.of(remoteAgentEventBuilder(context)))
.map(builder -> builder.turnComplete(true))
.map(builder -> builder.partial(false))
.map(Event.Builder::build);
} else {
return messageEvent;
}
}
throw new IllegalArgumentException(
"Unsupported TaskUpdateEvent type: " + updateEvent.getClass());
Expand All @@ -221,14 +236,28 @@ public static Event messageToEvent(Message message, InvocationContext invocation
* thought field to true, to mark them as thought updates.
*/
public static Event messageToEvent(
Message message, InvocationContext invocationContext, boolean isPending) {
Message message, InvocationContext invocationContext, boolean isPending, boolean isFailed) {

ImmutableList<com.google.genai.types.Part> genaiParts =
PartConverter.toGenaiParts(message.getParts()).stream()
.map(part -> part.toBuilder().thought(isPending).build())
.collect(toImmutableList());
Event.Builder builder = remoteAgentEventBuilder(invocationContext);

return remoteAgentEventBuilder(invocationContext).content(fromModelParts(genaiParts)).build();
if (isFailed) {
Optional.ofNullable(Iterables.getFirst(message.getParts(), null))
.ifPresent(
errorPart -> {
if (errorPart instanceof TextPart textPart) {
builder.errorMessage(textPart.getText());
}
});
} else {
ImmutableList<com.google.genai.types.Part> genaiParts =
PartConverter.toGenaiParts(message.getParts()).stream()
.map(part -> part.toBuilder().thought(isPending).build())
.collect(toImmutableList());

builder.content(fromModelParts(genaiParts));
}

return builder.build();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ private Task.Builder testTask() {
return new Task.Builder().id("task-1").contextId("context-1");
}

private static TaskStatusUpdateEvent.Builder testTaskStatusUpdateEvent() {
return new TaskStatusUpdateEvent.Builder().taskId("task-1").contextId("context-1");
}

@Test
public void eventsToMessage_withNullEvents_returnsEmptyAgentMessage() {
Message message = ResponseConverter.eventsToMessage(null, "context-1", "task-1");
Expand Down Expand Up @@ -330,6 +334,72 @@ public void clientEventToEvent_withTaskArtifactUpdateEvent_withLastChunkFalse_re
assertThat(optionalEvent).isEmpty();
}

@Test
public void clientEventToEvent_withFinalTaskStatusUpdateEvent_withMessage_returnsEvent() {
Message statusMessage =
new Message.Builder()
.role(Message.Role.AGENT)
.parts(ImmutableList.of(new TextPart("Final status message")))
.build();
TaskStatus status = new TaskStatus(TaskState.COMPLETED, statusMessage, null);
TaskStatusUpdateEvent updateEvent =
testTaskStatusUpdateEvent().isFinal(true).status(status).build();

TaskUpdateEvent event = new TaskUpdateEvent(testTask().status(status).build(), updateEvent);

Optional<Event> optionalEvent = ResponseConverter.clientEventToEvent(event, invocationContext);
assertThat(optionalEvent).isPresent();
Event resultEvent = optionalEvent.get();
assertThat(resultEvent.content().get().parts().get().get(0).text())
.hasValue("Final status message");
assertThat(resultEvent.content().get().parts().get().get(0).thought()).hasValue(false);
assertThat(resultEvent.partial().orElse(false)).isFalse();
assertThat(resultEvent.turnComplete()).hasValue(true);
}

@Test
public void clientEventToEvent_withFinalTaskStatusUpdateEvent_withoutMessage_returnsEvent() {
TaskStatus status = new TaskStatus(TaskState.COMPLETED, null, null);
TaskStatusUpdateEvent updateEvent =
new TaskStatusUpdateEvent("task-id-1", status, "context-1", true, null);
TaskUpdateEvent event = new TaskUpdateEvent(testTask().status(status).build(), updateEvent);

Optional<Event> optionalEvent = ResponseConverter.clientEventToEvent(event, invocationContext);
assertThat(optionalEvent).isPresent();
Event resultEvent = optionalEvent.get();
assertThat(resultEvent.turnComplete()).hasValue(true);
}

@Test
public void clientEventToEvent_withNonFinalTaskStatusUpdateEvent_withoutMessage_returnsEmpty() {
TaskStatus status = new TaskStatus(TaskState.WORKING, null, null);
TaskStatusUpdateEvent updateEvent =
new TaskStatusUpdateEvent("task-id-1", status, "context-1", false, null);
TaskUpdateEvent event = new TaskUpdateEvent(testTask().status(status).build(), updateEvent);

Optional<Event> optionalEvent = ResponseConverter.clientEventToEvent(event, invocationContext);
assertThat(optionalEvent).isEmpty();
}

@Test
public void clientEventToEvent_withFailedTaskStatusUpdateEvent_returnsErrorEvent() {
Message statusMessage =
new Message.Builder()
.role(Message.Role.AGENT)
.parts(ImmutableList.of(new TextPart("Task failed")))
.build();
TaskStatus status = new TaskStatus(TaskState.FAILED, statusMessage, null);
TaskStatusUpdateEvent updateEvent =
new TaskStatusUpdateEvent("task-id-1", status, "context-1", true, null);
TaskUpdateEvent event = new TaskUpdateEvent(testTask().status(status).build(), updateEvent);

Optional<Event> optionalEvent = ResponseConverter.clientEventToEvent(event, invocationContext);
assertThat(optionalEvent).isPresent();
Event resultEvent = optionalEvent.get();
assertThat(resultEvent.errorMessage()).hasValue("Task failed");
assertThat(resultEvent.turnComplete()).hasValue(true);
}

private static final class TestAgent extends BaseAgent {
TestAgent() {
super("test_agent", "test", ImmutableList.of(), null, null);
Expand Down