Skip to content

Commit 26afc43

Browse files
authored
Merge branch 'main' into github_dev_mcp_tool_schema_log
2 parents 1b01dcb + 383297a commit 26afc43

File tree

16 files changed

+1165
-53
lines changed

16 files changed

+1165
-53
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Agent Development Kit (ADK) for Java
22

33
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)
4+
[![Maven Central](https://img.shields.io/maven-central/v/com.google.adk/google-adk)](https://search.maven.org/artifact/com.google.adk/google-adk)
45
[![r/agentdevelopmentkit](https://img.shields.io/badge/Reddit-r%2Fagentdevelopmentkit-FF4500?style=flat&logo=reddit&logoColor=white)](https://www.reddit.com/r/agentdevelopmentkit/)
56

67
<html>

contrib/langchain4j/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,4 @@
136136
<scope>test</scope>
137137
</dependency>
138138
</dependencies>
139-
</project>
139+
</project>
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
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 not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package com.google.adk.agents;
19+
20+
import io.reactivex.rxjava3.disposables.Disposable;
21+
import javax.annotation.Nullable;
22+
23+
/** Manages streaming tool related resources during invocation. */
24+
public class ActiveStreamingTool {
25+
@Nullable private Disposable task;
26+
@Nullable private LiveRequestQueue stream;
27+
28+
public ActiveStreamingTool(Disposable task) {
29+
this(task, null);
30+
}
31+
32+
public ActiveStreamingTool(LiveRequestQueue stream) {
33+
this(null, stream);
34+
}
35+
36+
public ActiveStreamingTool(Disposable task, LiveRequestQueue stream) {
37+
this.task = task;
38+
this.stream = stream;
39+
}
40+
41+
public ActiveStreamingTool() {}
42+
43+
/**
44+
* Returns the active task of this streaming tool.
45+
*
46+
* @return The active task.
47+
*/
48+
@Nullable
49+
public Disposable task() {
50+
return task;
51+
}
52+
53+
/**
54+
* Sets the active task of this streaming tool.
55+
*
56+
* @param task The new active task.
57+
*/
58+
public void task(@Nullable Disposable task) {
59+
this.task = task;
60+
}
61+
62+
/**
63+
* Returns the active stream of this streaming tool.
64+
*
65+
* @return The active stream.
66+
*/
67+
@Nullable
68+
public LiveRequestQueue stream() {
69+
return stream;
70+
}
71+
72+
/**
73+
* Sets the active stream of this streaming tool.
74+
*
75+
* @param stream The new active stream.
76+
*/
77+
public void stream(@Nullable LiveRequestQueue stream) {
78+
this.stream = stream;
79+
}
80+
}

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@
1616

1717
package com.google.adk.agents;
1818

19+
import com.google.adk.artifacts.ListArtifactsResponse;
1920
import com.google.adk.events.EventActions;
2021
import com.google.adk.sessions.State;
2122
import com.google.genai.types.Part;
2223
import io.reactivex.rxjava3.core.Maybe;
24+
import io.reactivex.rxjava3.core.Single;
25+
import java.util.List;
2326
import java.util.Optional;
2427

2528
/** The context of various callbacks for an agent invocation. */
@@ -51,6 +54,24 @@ public EventActions eventActions() {
5154
return eventActions;
5255
}
5356

57+
/**
58+
* Lists the filenames of the artifacts attached to the current session.
59+
*
60+
* @return the list of artifact filenames
61+
*/
62+
public Single<List<String>> listArtifacts() {
63+
if (invocationContext.artifactService() == null) {
64+
throw new IllegalStateException("Artifact service is not initialized.");
65+
}
66+
return invocationContext
67+
.artifactService()
68+
.listArtifactKeys(
69+
invocationContext.session().appName(),
70+
invocationContext.session().userId(),
71+
invocationContext.session().id())
72+
.map(ListArtifactsResponse::filenames);
73+
}
74+
5475
/**
5576
* Loads an artifact from the artifact service associated with the current session.
5677
*

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

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@
2121
import com.google.adk.sessions.BaseSessionService;
2222
import com.google.adk.sessions.Session;
2323
import com.google.genai.types.Content;
24+
import java.util.Map;
2425
import java.util.Objects;
2526
import java.util.Optional;
2627
import java.util.UUID;
28+
import java.util.concurrent.ConcurrentHashMap;
2729
import javax.annotation.Nullable;
2830

2931
/** The context for an agent invocation. */
@@ -32,6 +34,7 @@ public class InvocationContext {
3234
private final BaseSessionService sessionService;
3335
private final BaseArtifactService artifactService;
3436
private final Optional<LiveRequestQueue> liveRequestQueue;
37+
private final Map<String, ActiveStreamingTool> activeStreamingTools = new ConcurrentHashMap<>();
3538

3639
private Optional<String> branch;
3740
private final String invocationId;
@@ -108,17 +111,20 @@ public static InvocationContext create(
108111
}
109112

110113
public static InvocationContext copyOf(InvocationContext other) {
111-
return new InvocationContext(
112-
other.sessionService,
113-
other.artifactService,
114-
other.liveRequestQueue,
115-
other.branch,
116-
other.invocationId,
117-
other.agent,
118-
other.session,
119-
other.userContent,
120-
other.runConfig,
121-
other.endInvocation);
114+
InvocationContext newContext =
115+
new InvocationContext(
116+
other.sessionService,
117+
other.artifactService,
118+
other.liveRequestQueue,
119+
other.branch,
120+
other.invocationId,
121+
other.agent,
122+
other.session,
123+
other.userContent,
124+
other.runConfig,
125+
other.endInvocation);
126+
newContext.activeStreamingTools.putAll(other.activeStreamingTools);
127+
return newContext;
122128
}
123129

124130
public BaseSessionService sessionService() {
@@ -129,6 +135,10 @@ public BaseArtifactService artifactService() {
129135
return artifactService;
130136
}
131137

138+
public Map<String, ActiveStreamingTool> activeStreamingTools() {
139+
return activeStreamingTools;
140+
}
141+
132142
public Optional<LiveRequestQueue> liveRequestQueue() {
133143
return liveRequestQueue;
134144
}
@@ -217,6 +227,7 @@ public boolean equals(Object o) {
217227
&& Objects.equals(sessionService, that.sessionService)
218228
&& Objects.equals(artifactService, that.artifactService)
219229
&& Objects.equals(liveRequestQueue, that.liveRequestQueue)
230+
&& Objects.equals(activeStreamingTools, that.activeStreamingTools)
220231
&& Objects.equals(branch, that.branch)
221232
&& Objects.equals(invocationId, that.invocationId)
222233
&& Objects.equals(agent, that.agent)
@@ -231,6 +242,7 @@ public int hashCode() {
231242
sessionService,
232243
artifactService,
233244
liveRequestQueue,
245+
activeStreamingTools,
234246
branch,
235247
invocationId,
236248
agent,

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

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.google.adk.flows.llmflows;
1818

1919
import com.google.adk.Telemetry;
20+
import com.google.adk.agents.ActiveStreamingTool;
2021
import com.google.adk.agents.BaseAgent;
2122
import com.google.adk.agents.CallbackContext;
2223
import com.google.adk.agents.Callbacks.AfterModelCallback;
@@ -168,11 +169,16 @@ protected Single<ResponseProcessingResult> postprocess(
168169
buildModelResponseEvent(baseEventForLlmResponse, llmRequest, updatedResponse);
169170
eventIterables.add(Collections.singleton(modelResponseEvent));
170171

171-
Maybe<Event> maybeFunctionCallEvent =
172-
modelResponseEvent.functionCalls().isEmpty()
173-
? Maybe.empty()
174-
: Functions.handleFunctionCalls(context, modelResponseEvent, llmRequest.tools());
175-
172+
Maybe<Event> maybeFunctionCallEvent;
173+
if (modelResponseEvent.functionCalls().isEmpty()) {
174+
maybeFunctionCallEvent = Maybe.empty();
175+
} else if (context.runConfig().streamingMode() == StreamingMode.BIDI) {
176+
maybeFunctionCallEvent =
177+
Functions.handleFunctionCallsLive(context, modelResponseEvent, llmRequest.tools());
178+
} else {
179+
maybeFunctionCallEvent =
180+
Functions.handleFunctionCalls(context, modelResponseEvent, llmRequest.tools());
181+
}
176182
return maybeFunctionCallEvent
177183
.map(Optional::of)
178184
.defaultIfEmpty(Optional.empty())
@@ -497,7 +503,22 @@ public Flowable<Event> runLive(InvocationContext invocationContext) {
497503
}
498504
});
499505

500-
Flowable<LiveRequest> liveRequests = invocationContext.liveRequestQueue().get().get();
506+
Flowable<LiveRequest> liveRequests =
507+
invocationContext
508+
.liveRequestQueue()
509+
.get()
510+
.get()
511+
.doOnNext(
512+
request -> {
513+
if (!invocationContext.activeStreamingTools().isEmpty()) {
514+
for (ActiveStreamingTool activeStreamingTool :
515+
invocationContext.activeStreamingTools().values()) {
516+
if (activeStreamingTool.stream() != null) {
517+
activeStreamingTool.stream().send(request);
518+
}
519+
}
520+
}
521+
});
501522
Disposable sendTask =
502523
historySent
503524
.observeOn(agent.executor().map(Schedulers::from).orElse(Schedulers.io()))

0 commit comments

Comments
 (0)