Skip to content

Commit d5e8e58

Browse files
google-genai-botcopybara-github
authored andcommitted
refactor:Refactor Runner to implement a Builder rather than a growing number of constructors
PiperOrigin-RevId: 839375782
1 parent e6755a2 commit d5e8e58

File tree

9 files changed

+1215
-448
lines changed

9 files changed

+1215
-448
lines changed

core/src/main/java/com/google/adk/agents/InvocationContext.java

Lines changed: 396 additions & 102 deletions
Large diffs are not rendered by default.

core/src/main/java/com/google/adk/agents/LlmAgent.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,16 @@ private void maybeSaveOutputToState(Event event) {
604604

605605
@Override
606606
protected Flowable<Event> runAsyncImpl(InvocationContext invocationContext) {
607-
return llmFlow.run(invocationContext).doOnNext(this::maybeSaveOutputToState);
607+
return llmFlow
608+
.run(invocationContext)
609+
.concatMap(
610+
event -> {
611+
this.maybeSaveOutputToState(event);
612+
if (invocationContext.shouldPauseInvocation(event)) {
613+
return Flowable.just(event).concatWith(Flowable.empty());
614+
}
615+
return Flowable.just(event);
616+
});
608617
}
609618

610619
@Override

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

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -156,36 +156,9 @@ protected Flowable<Event> postprocess(
156156
}
157157

158158
return currentLlmResponse.flatMapPublisher(
159-
updatedResponse -> {
160-
Flowable<Event> processorEvents = Flowable.fromIterable(Iterables.concat(eventIterables));
161-
162-
if (updatedResponse.content().isEmpty()
163-
&& updatedResponse.errorCode().isEmpty()
164-
&& !updatedResponse.interrupted().orElse(false)
165-
&& !updatedResponse.turnComplete().orElse(false)) {
166-
return processorEvents;
167-
}
168-
169-
Event modelResponseEvent =
170-
buildModelResponseEvent(baseEventForLlmResponse, llmRequest, updatedResponse);
171-
172-
Flowable<Event> modelEventStream = Flowable.just(modelResponseEvent);
173-
174-
if (modelResponseEvent.functionCalls().isEmpty()) {
175-
return processorEvents.concatWith(modelEventStream);
176-
}
177-
178-
Maybe<Event> maybeFunctionCallEvent;
179-
if (context.runConfig().streamingMode() == StreamingMode.BIDI) {
180-
maybeFunctionCallEvent =
181-
Functions.handleFunctionCallsLive(context, modelResponseEvent, llmRequest.tools());
182-
} else {
183-
maybeFunctionCallEvent =
184-
Functions.handleFunctionCalls(context, modelResponseEvent, llmRequest.tools());
185-
}
186-
187-
return processorEvents.concatWith(modelEventStream).concatWith(maybeFunctionCallEvent);
188-
});
159+
updatedResponse ->
160+
buildPostprocessingEvents(
161+
updatedResponse, eventIterables, context, baseEventForLlmResponse, llmRequest));
189162
}
190163

191164
/**
@@ -623,6 +596,45 @@ public void onError(Throwable e) {
623596
*
624597
* @return A fully constructed {@link Event} representing the LLM response.
625598
*/
599+
private Flowable<Event> buildPostprocessingEvents(
600+
LlmResponse updatedResponse,
601+
List<Iterable<Event>> eventIterables,
602+
InvocationContext context,
603+
Event baseEventForLlmResponse,
604+
LlmRequest llmRequest) {
605+
Flowable<Event> processorEvents = Flowable.fromIterable(Iterables.concat(eventIterables));
606+
if (updatedResponse.content().isEmpty()
607+
&& updatedResponse.errorCode().isEmpty()
608+
&& !updatedResponse.interrupted().orElse(false)
609+
&& !updatedResponse.turnComplete().orElse(false)) {
610+
return processorEvents;
611+
}
612+
613+
Event modelResponseEvent =
614+
buildModelResponseEvent(baseEventForLlmResponse, llmRequest, updatedResponse);
615+
if (modelResponseEvent.functionCalls().isEmpty()) {
616+
return processorEvents.concatWith(Flowable.just(modelResponseEvent));
617+
}
618+
619+
Maybe<Event> maybeFunctionResponseEvent =
620+
context.runConfig().streamingMode() == StreamingMode.BIDI
621+
? Functions.handleFunctionCallsLive(context, modelResponseEvent, llmRequest.tools())
622+
: Functions.handleFunctionCalls(context, modelResponseEvent, llmRequest.tools());
623+
624+
Flowable<Event> functionEvents =
625+
maybeFunctionResponseEvent.flatMapPublisher(
626+
functionResponseEvent -> {
627+
Optional<Event> toolConfirmationEvent =
628+
Functions.generateRequestConfirmationEvent(
629+
context, modelResponseEvent, functionResponseEvent);
630+
return toolConfirmationEvent.isPresent()
631+
? Flowable.just(toolConfirmationEvent.get(), functionResponseEvent)
632+
: Flowable.just(functionResponseEvent);
633+
});
634+
635+
return processorEvents.concatWith(Flowable.just(modelResponseEvent)).concatWith(functionEvents);
636+
}
637+
626638
private Event buildModelResponseEvent(
627639
Event baseEventForLlmResponse, LlmRequest llmRequest, LlmResponse llmResponse) {
628640
Event.Builder eventBuilder =
@@ -640,10 +652,13 @@ private Event buildModelResponseEvent(
640652

641653
Event event = eventBuilder.build();
642654

655+
logger.info("event: {} functionCalls: {}", event, event.functionCalls());
656+
643657
if (!event.functionCalls().isEmpty()) {
644658
Functions.populateClientFunctionCallId(event);
645659
Set<String> longRunningToolIds =
646660
Functions.getLongRunningFunctionCalls(event.functionCalls(), llmRequest.tools());
661+
logger.info("longRunningToolIds: {}", longRunningToolIds);
647662
if (!longRunningToolIds.isEmpty()) {
648663
event.setLongRunningToolIds(Optional.of(longRunningToolIds));
649664
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2025 Google LLC
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 com.google.adk.flows.llmflows;
17+
18+
/**
19+
* An app contains Resumability configuration for the agents.
20+
*
21+
* @param isResumable Whether the app is resumable.
22+
*/
23+
public record ResumabilityConfig(boolean isResumable) {
24+
25+
/** Creates a new {@code ResumabilityConfig} with resumability disabled. */
26+
public ResumabilityConfig() {
27+
this(false);
28+
}
29+
}

0 commit comments

Comments
 (0)