Skip to content

Commit e47d78d

Browse files
authored
Merge branch 'main' into google_dev_mcp_sse_param
2 parents 4769406 + 7c7d779 commit e47d78d

File tree

61 files changed

+3691
-923
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+3691
-923
lines changed

CONTRIBUTING.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,35 @@ information on using pull requests.
3434

3535
## PR policy
3636

37+
### Format
38+
39+
Code must be formatted according to the
40+
[Google Java Style Guide](https://google.github.io/styleguide/javaguide.html).
41+
42+
The Maven build will automagically run
43+
[`google-java-format`](https://github.com/google/google-java-format) when you
44+
locally build this project.
45+
46+
Pull requests will fail to build if you forget to commit reformatted code, and
47+
cannot be merged until you fix this.
48+
49+
### Single Commit
50+
51+
Pull Requests must contain only a **single commit.**
52+
53+
This is due to how Google replicates this Git repository both into and from its
54+
internal _monorepo_ (see [Wikipedia](https://en.wikipedia.org/wiki/Monorepo) and
55+
[Paper](https://research.google/pubs/why-google-stores-billions-of-lines-of-code-in-a-single-repository/))
56+
with [🦛 Copybara](https://github.com/google/copybara).
57+
58+
When adjusting a PR to code review feedback, please use `git commit --amend`.
59+
60+
You can use `git rebase -i main` to _meld/squash_ existing commits into one.
61+
62+
Then use `git push --force-with-lease` to update the branch of your PR.
63+
64+
We cannot merge your PR until you fix this.
65+
3766
### AI Generated code
3867

3968
It's ok to generate the first draft using AI but we would like code which has

core/pom.xml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
<java-websocket.version>1.6.0</java-websocket.version>
4242
<jackson.version>2.19.0</jackson.version>
4343
<okhttp.version>4.12.0</okhttp.version>
44+
<docker-java.version>3.3.6</docker-java.version>
4445
</properties>
4546

4647
<dependencies>
@@ -62,6 +63,16 @@
6263
<groupId>com.google.cloud</groupId>
6364
<artifactId>google-cloud-aiplatform</artifactId>
6465
</dependency>
66+
<dependency>
67+
<groupId>com.github.docker-java</groupId>
68+
<artifactId>docker-java</artifactId>
69+
<version>${docker-java.version}</version>
70+
</dependency>
71+
<dependency>
72+
<groupId>com.github.docker-java</groupId>
73+
<artifactId>docker-java-transport-httpclient5</artifactId>
74+
<version>${docker-java.version}</version>
75+
</dependency>
6576
<dependency>
6677
<groupId> io.modelcontextprotocol.sdk</groupId>
6778
<artifactId>mcp</artifactId>
@@ -178,6 +189,11 @@
178189
<artifactId>rxjava</artifactId>
179190
<version>3.1.5</version>
180191
</dependency>
192+
<dependency>
193+
<groupId>io.projectreactor</groupId>
194+
<artifactId>reactor-core</artifactId>
195+
<version>3.7.0</version>
196+
</dependency>
181197
<dependency>
182198
<groupId>com.github.tomakehurst</groupId>
183199
<artifactId>wiremock-jre8</artifactId>

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

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@
1616

1717
package com.google.adk.agents;
1818

19-
import static com.google.common.base.Strings.isNullOrEmpty;
20-
2119
import com.fasterxml.jackson.databind.DeserializationFeature;
2220
import com.fasterxml.jackson.databind.ObjectMapper;
2321
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
22+
import com.google.adk.utils.ComponentRegistry;
2423
import java.io.File;
2524
import java.io.FileInputStream;
2625
import java.io.IOException;
@@ -59,7 +58,8 @@ public static BaseAgent fromConfig(String configPath) throws ConfigurationExcept
5958
try {
6059
// Load the base config to determine the agent class
6160
BaseAgentConfig baseConfig = loadConfigAsType(absolutePath, BaseAgentConfig.class);
62-
Class<? extends BaseAgent> agentClass = resolveAgentClass(baseConfig.agentClass());
61+
Class<? extends BaseAgent> agentClass =
62+
ComponentRegistry.resolveAgentClass(baseConfig.agentClass());
6363

6464
// Load the config file with the specific config class
6565
Class<? extends BaseAgentConfig> configClass = getConfigClassForAgent(agentClass);
@@ -97,32 +97,6 @@ private static <T extends BaseAgentConfig> T loadConfigAsType(
9797
}
9898
}
9999

100-
/**
101-
* Resolves the agent class based on the agent class name from the configuration.
102-
*
103-
* @param agentClassName the name of the agent class from the config
104-
* @return the corresponding agent class
105-
* @throws ConfigurationException if the agent class is not supported
106-
*/
107-
private static Class<? extends BaseAgent> resolveAgentClass(String agentClassName)
108-
throws ConfigurationException {
109-
// If no agent_class is specified in the yaml file, it will default to LlmAgent.
110-
if (isNullOrEmpty(agentClassName) || agentClassName.equals("LlmAgent")) {
111-
return LlmAgent.class;
112-
}
113-
114-
// TODO: Support more agent classes
115-
// Example for future extensions:
116-
// if (agentClassName.equals("CustomAgent")) {
117-
// return CustomAgent.class;
118-
// }
119-
120-
throw new ConfigurationException(
121-
"agentClass '"
122-
+ agentClassName
123-
+ "' is not supported. It must be a subclass of BaseAgent.");
124-
}
125-
126100
/**
127101
* Maps agent classes to their corresponding config classes.
128102
*

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

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818

1919
import com.google.adk.artifacts.BaseArtifactService;
2020
import com.google.adk.exceptions.LlmCallsLimitExceededException;
21+
import com.google.adk.memory.BaseMemoryService;
2122
import com.google.adk.sessions.BaseSessionService;
2223
import com.google.adk.sessions.Session;
24+
import com.google.errorprone.annotations.InlineMe;
2325
import com.google.genai.types.Content;
2426
import java.util.Map;
2527
import java.util.Objects;
@@ -33,6 +35,7 @@ public class InvocationContext {
3335

3436
private final BaseSessionService sessionService;
3537
private final BaseArtifactService artifactService;
38+
private final BaseMemoryService memoryService;
3639
private final Optional<LiveRequestQueue> liveRequestQueue;
3740
private final Map<String, ActiveStreamingTool> activeStreamingTools = new ConcurrentHashMap<>();
3841

@@ -46,9 +49,10 @@ public class InvocationContext {
4649
private boolean endInvocation;
4750
private final InvocationCostManager invocationCostManager = new InvocationCostManager();
4851

49-
private InvocationContext(
52+
public InvocationContext(
5053
BaseSessionService sessionService,
5154
BaseArtifactService artifactService,
55+
BaseMemoryService memoryService,
5256
Optional<LiveRequestQueue> liveRequestQueue,
5357
Optional<String> branch,
5458
String invocationId,
@@ -59,6 +63,7 @@ private InvocationContext(
5963
boolean endInvocation) {
6064
this.sessionService = sessionService;
6165
this.artifactService = artifactService;
66+
this.memoryService = memoryService;
6267
this.liveRequestQueue = liveRequestQueue;
6368
this.branch = branch;
6469
this.invocationId = invocationId;
@@ -69,6 +74,16 @@ private InvocationContext(
6974
this.endInvocation = endInvocation;
7075
}
7176

77+
/**
78+
* @deprecated Use the {@link #InvocationContext} constructor directly instead
79+
*/
80+
@InlineMe(
81+
replacement =
82+
"new InvocationContext(sessionService, artifactService, null, Optional.empty(),"
83+
+ " Optional.empty(), invocationId, agent, session, Optional.ofNullable(userContent),"
84+
+ " runConfig, false)",
85+
imports = {"com.google.adk.agents.InvocationContext", "java.util.Optional"})
86+
@Deprecated
7287
public static InvocationContext create(
7388
BaseSessionService sessionService,
7489
BaseArtifactService artifactService,
@@ -80,7 +95,8 @@ public static InvocationContext create(
8095
return new InvocationContext(
8196
sessionService,
8297
artifactService,
83-
Optional.empty(),
98+
/* memoryService= */ null,
99+
/* liveRequestQueue= */ Optional.empty(),
84100
/* branch= */ Optional.empty(),
85101
invocationId,
86102
agent,
@@ -90,6 +106,17 @@ public static InvocationContext create(
90106
false);
91107
}
92108

109+
/**
110+
* @deprecated Use the {@link #InvocationContext} constructor directly instead
111+
*/
112+
@InlineMe(
113+
replacement =
114+
"new InvocationContext(sessionService, artifactService, null,"
115+
+ " Optional.ofNullable(liveRequestQueue), Optional.empty(),"
116+
+ " InvocationContext.newInvocationContextId(), agent, session, Optional.empty(),"
117+
+ " runConfig, false)",
118+
imports = {"com.google.adk.agents.InvocationContext", "java.util.Optional"})
119+
@Deprecated
93120
public static InvocationContext create(
94121
BaseSessionService sessionService,
95122
BaseArtifactService artifactService,
@@ -100,6 +127,7 @@ public static InvocationContext create(
100127
return new InvocationContext(
101128
sessionService,
102129
artifactService,
130+
/* memoryService= */ null,
103131
Optional.ofNullable(liveRequestQueue),
104132
/* branch= */ Optional.empty(),
105133
InvocationContext.newInvocationContextId(),
@@ -115,6 +143,7 @@ public static InvocationContext copyOf(InvocationContext other) {
115143
new InvocationContext(
116144
other.sessionService,
117145
other.artifactService,
146+
other.memoryService,
118147
other.liveRequestQueue,
119148
other.branch,
120149
other.invocationId,
@@ -135,6 +164,10 @@ public BaseArtifactService artifactService() {
135164
return artifactService;
136165
}
137166

167+
public BaseMemoryService memoryService() {
168+
return memoryService;
169+
}
170+
138171
public Map<String, ActiveStreamingTool> activeStreamingTools() {
139172
return activeStreamingTools;
140173
}
@@ -226,6 +259,7 @@ public boolean equals(Object o) {
226259
return endInvocation == that.endInvocation
227260
&& Objects.equals(sessionService, that.sessionService)
228261
&& Objects.equals(artifactService, that.artifactService)
262+
&& Objects.equals(memoryService, that.memoryService)
229263
&& Objects.equals(liveRequestQueue, that.liveRequestQueue)
230264
&& Objects.equals(activeStreamingTools, that.activeStreamingTools)
231265
&& Objects.equals(branch, that.branch)
@@ -241,6 +275,7 @@ public int hashCode() {
241275
return Objects.hash(
242276
sessionService,
243277
artifactService,
278+
memoryService,
244279
liveRequestQueue,
245280
activeStreamingTools,
246281
branch,

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

Lines changed: 9 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.google.adk.agents;
1818

19+
import static com.google.common.base.Strings.isNullOrEmpty;
1920
import static com.google.common.base.Strings.nullToEmpty;
2021
import static java.util.stream.Collectors.joining;
2122

@@ -53,7 +54,7 @@
5354
import com.google.adk.tools.BaseTool;
5455
import com.google.adk.tools.BaseTool.ToolConfig;
5556
import com.google.adk.tools.BaseToolset;
56-
import com.google.common.base.CaseFormat;
57+
import com.google.adk.utils.ComponentRegistry;
5758
import com.google.common.base.Preconditions;
5859
import com.google.common.collect.ImmutableList;
5960
import com.google.errorprone.annotations.CanIgnoreReturnValue;
@@ -63,7 +64,6 @@
6364
import io.reactivex.rxjava3.core.Flowable;
6465
import io.reactivex.rxjava3.core.Maybe;
6566
import io.reactivex.rxjava3.core.Single;
66-
import java.lang.reflect.Constructor;
6767
import java.util.ArrayList;
6868
import java.util.List;
6969
import java.util.Map;
@@ -950,23 +950,21 @@ private static ImmutableList<BaseTool> resolveTools(
950950

951951
for (ToolConfig toolConfig : toolConfigs) {
952952
try {
953-
String toolName = toolConfig.name();
954-
if (toolName == null || toolName.trim().isEmpty()) {
953+
if (isNullOrEmpty(toolConfig.name())) {
955954
throw new ConfigurationException("Tool name cannot be empty");
956955
}
957956

958-
toolName = toolName.trim();
959-
BaseTool tool;
960-
961-
if (!toolName.contains(".")) {
962-
tool = resolveBuiltInTool(toolName, toolConfig);
957+
String toolName = toolConfig.name().trim();
958+
Optional<BaseTool> toolOpt = ComponentRegistry.resolveToolInstance(toolName);
959+
if (toolOpt.isPresent()) {
960+
resolvedTools.add(toolOpt.get());
963961
} else {
964962
// TODO: Support user-defined tools
963+
// TODO: Support using tool class via ComponentRegistry.resolveToolClass
965964
logger.debug("configAbsPath is: {}", configAbsPath);
966-
throw new ConfigurationException("User-defined tools are not yet supported");
965+
throw new ConfigurationException("Tool not found: " + toolName);
967966
}
968967

969-
resolvedTools.add(tool);
970968
logger.debug("Successfully resolved tool: {}", toolConfig.name());
971969
} catch (Exception e) {
972970
String errorMsg = "Failed to resolve tool: " + toolConfig.name();
@@ -977,77 +975,4 @@ private static ImmutableList<BaseTool> resolveTools(
977975

978976
return ImmutableList.copyOf(resolvedTools);
979977
}
980-
981-
private static BaseTool resolveBuiltInTool(String toolName, ToolConfig toolConfig)
982-
throws ConfigurationException {
983-
try {
984-
logger.debug("Resolving built-in tool: {}", toolName);
985-
// TODO: Handle built-in tool name end with Tool while config yaml file does not.
986-
// e.g.google_search in config yaml file and GoogleSearchTool in tool class name.
987-
String pascalCaseToolName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, toolName);
988-
String className = "com.google.adk.tools." + pascalCaseToolName;
989-
Class<?> toolClass;
990-
try {
991-
toolClass = Class.forName(className);
992-
logger.debug("Successfully loaded tool class: {}", className);
993-
} catch (ClassNotFoundException e) {
994-
String fallbackClassName = "com.google.adk.tools." + toolName;
995-
try {
996-
toolClass = Class.forName(fallbackClassName);
997-
} catch (ClassNotFoundException e2) {
998-
throw new ConfigurationException(
999-
"Built-in tool not found: "
1000-
+ toolName
1001-
+ ". Expected class: "
1002-
+ className
1003-
+ " or "
1004-
+ fallbackClassName,
1005-
e2);
1006-
}
1007-
}
1008-
1009-
if (!BaseTool.class.isAssignableFrom(toolClass)) {
1010-
throw new ConfigurationException(
1011-
"Built-in tool class " + toolClass.getName() + " does not extend BaseTool");
1012-
}
1013-
1014-
@SuppressWarnings("unchecked")
1015-
Class<? extends BaseTool> baseToolClass = (Class<? extends BaseTool>) toolClass;
1016-
1017-
BaseTool tool = createToolInstance(baseToolClass, toolConfig);
1018-
logger.info(
1019-
"Successfully created built-in tool: {} (class: {})", toolName, toolClass.getName());
1020-
1021-
return tool;
1022-
1023-
} catch (Exception e) {
1024-
logger.error("Failed to create built-in tool: {}", toolName, e);
1025-
throw new ConfigurationException("Failed to create built-in tool: " + toolName, e);
1026-
}
1027-
}
1028-
1029-
private static BaseTool createToolInstance(
1030-
Class<? extends BaseTool> toolClass, ToolConfig toolConfig)
1031-
throws ConfigAgentUtils.ConfigurationException {
1032-
1033-
try {
1034-
// TODO:implement constructor with ToolArgsConfig
1035-
logger.debug("ToolConfig is: {}", toolConfig);
1036-
1037-
// Try default constructor
1038-
try {
1039-
Constructor<? extends BaseTool> constructor = toolClass.getConstructor();
1040-
return constructor.newInstance();
1041-
} catch (NoSuchMethodException e) {
1042-
// Continue
1043-
}
1044-
1045-
throw new ConfigAgentUtils.ConfigurationException(
1046-
"No suitable constructor found for tool class: " + toolClass.getName());
1047-
1048-
} catch (Exception e) {
1049-
throw new ConfigAgentUtils.ConfigurationException(
1050-
"Failed to instantiate tool class: " + toolClass.getName(), e);
1051-
}
1052-
}
1053978
}

0 commit comments

Comments
 (0)