Skip to content

Commit 5bc3ef8

Browse files
google-genai-botcopybara-github
authored andcommitted
fix: Exit from rearrangeEventsForLatestFunctionResponse if size of events is less than 2
PiperOrigin-RevId: 877845164
1 parent 2ec0e90 commit 5bc3ef8

2 files changed

Lines changed: 53 additions & 4 deletions

File tree

core/src/main/java/com/google/adk/flows/llmflows/Contents.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,11 @@ private static boolean isEventBelongsToBranch(Optional<String> invocationBranchO
406406
* @return A new list of events with the appropriate rearrangement.
407407
*/
408408
private static List<Event> rearrangeEventsForLatestFunctionResponse(List<Event> events) {
409+
if (events.size() < 2) {
410+
// No need to process, since there is no function_call.
411+
return events;
412+
}
413+
409414
// TODO: b/412663475 - Handle parallel function calls within the same event. Currently, this
410415
// throws an error.
411416
if (events.isEmpty() || Iterables.getLast(events).functionResponses().isEmpty()) {

core/src/test/java/com/google/adk/flows/llmflows/ContentsTest.java

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,9 @@ public void rearrangeLatest_multipleFRsForSameFCAsync_returnsMergedFR() {
142142
@Test
143143
public void rearrangeLatest_missingFCEvent_throwsException() {
144144
Event frEvent = createFunctionResponseEvent("fr1", "tool1", "call1");
145-
ImmutableList<Event> events = ImmutableList.of(createUserEvent("u1", "Query"), frEvent);
145+
Event frEvent2 = createFunctionResponseEvent("fr2", "tool1", "call1");
146+
ImmutableList<Event> events =
147+
ImmutableList.of(createUserEvent("u1", "Query"), frEvent, frEvent2);
146148

147149
assertThrows(IllegalStateException.class, () -> runContentsProcessor(events));
148150
}
@@ -473,10 +475,12 @@ public void processRequest_includeContentsNone_asyncFRAcrossTurns_throwsExceptio
473475
Event fc1 = createFunctionCallEvent("fc1", "tool1", "call1");
474476
Event u2 = createUserEvent("u2", "Query 2");
475477
Event fr1 = createFunctionResponseEvent("fr1", "tool1", "call1"); // FR for fc1
478+
Event fr2 = createFunctionResponseEvent("fr2", "tool2", "call1"); // FR for fc2
476479

477-
ImmutableList<Event> events = ImmutableList.of(u1, fc1, u2, fr1);
480+
ImmutableList<Event> events = ImmutableList.of(u1, fc1, u2, fr1, fr2);
478481

479-
// The current turn starts from u2. fc1 is not in the sublist [u2, fr1], so rearrangement fails.
482+
// The current turn starts from u2. fc1 is not in the sublist [u2, fr1, fr2], so rearrangement
483+
// fails.
480484
IllegalStateException e =
481485
assertThrows(
482486
IllegalStateException.class,
@@ -486,6 +490,19 @@ public void processRequest_includeContentsNone_asyncFRAcrossTurns_throwsExceptio
486490
.contains("No function call event found for function response IDs: [call1]");
487491
}
488492

493+
@Test
494+
public void processRequest_notEnoughEvents_returnsOriginalList() {
495+
Event fr1 =
496+
createFunctionCallAndResponseEvent(
497+
"fr1", "tool1", "call1", ImmutableMap.of("result", "ok"), "user");
498+
499+
ImmutableList<Event> events = ImmutableList.of(fr1);
500+
501+
List<Content> result =
502+
runContentsProcessorWithIncludeContents(events, LlmAgent.IncludeContents.NONE, "A2A-agent");
503+
assertThat(result).isEmpty();
504+
}
505+
489506
@Test
490507
public void processRequest_includeContentsNone_asyncFRWithinTurn() {
491508
Event u1 = createUserEvent("u1", "Query 1");
@@ -883,13 +900,40 @@ private static Event createFunctionResponseEvent(
883900
.build();
884901
}
885902

903+
private static Event createFunctionCallAndResponseEvent(
904+
String id, String toolName, String callId, Map<String, Object> response, String author) {
905+
return Event.builder()
906+
.id(id)
907+
.author(author)
908+
.invocationId("invocationId")
909+
.content(
910+
Content.fromParts(
911+
Part.builder()
912+
.functionCall(FunctionCall.builder().name(toolName).id(callId).build())
913+
.build(),
914+
Part.builder()
915+
.functionResponse(
916+
FunctionResponse.builder()
917+
.name(toolName)
918+
.id(callId)
919+
.response(response)
920+
.build())
921+
.build()))
922+
.build();
923+
}
924+
886925
private List<Content> runContentsProcessor(List<Event> events) {
887926
return runContentsProcessorWithIncludeContents(events, LlmAgent.IncludeContents.DEFAULT);
888927
}
889928

890929
private List<Content> runContentsProcessorWithIncludeContents(
891930
List<Event> events, LlmAgent.IncludeContents includeContents) {
892-
LlmAgent agent = LlmAgent.builder().name(AGENT).includeContents(includeContents).build();
931+
return runContentsProcessorWithIncludeContents(events, includeContents, AGENT);
932+
}
933+
934+
private List<Content> runContentsProcessorWithIncludeContents(
935+
List<Event> events, LlmAgent.IncludeContents includeContents, String agentName) {
936+
LlmAgent agent = LlmAgent.builder().name(agentName).includeContents(includeContents).build();
893937
Session session =
894938
sessionService.createSession("test-app", "test-user", null, "test-session").blockingGet();
895939
session.events().addAll(events);

0 commit comments

Comments
 (0)