Skip to content

Commit 43613a4

Browse files
google-genai-botcopybara-github
authored andcommitted
feat: add fromConfig method to LongRunningFunctionTool
The config's `func` parameter is interpreted as a name of a FuncTool registered elsewhere, that the LongRunningFunction tool is wrapping PiperOrigin-RevId: 845734852
1 parent 7ff08f2 commit 43613a4

4 files changed

Lines changed: 89 additions & 0 deletions

File tree

core/src/main/java/com/google/adk/tools/FunctionTool.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,17 @@ public Method func() {
185185
return func;
186186
}
187187

188+
/** Returns the underlying function's {@link Object} instance if present. */
189+
@Nullable
190+
Object instance() {
191+
return instance;
192+
}
193+
194+
/** Returns whether the function requires confirmation */
195+
boolean requireConfirmation() {
196+
return requireConfirmation;
197+
}
198+
188199
/** Returns true if the wrapped function returns a Flowable and can be used for streaming. */
189200
public boolean isStreaming() {
190201
Type returnType = func.getGenericReturnType();

core/src/main/java/com/google/adk/tools/LongRunningFunctionTool.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package com.google.adk.tools;
1818

19+
import com.fasterxml.jackson.core.type.TypeReference;
20+
import com.google.adk.utils.ComponentRegistry;
1921
import java.lang.reflect.Method;
2022
import javax.annotation.Nullable;
2123

@@ -70,6 +72,11 @@ public static LongRunningFunctionTool create(
7072
return new LongRunningFunctionTool(instance, method, requireConfirmation);
7173
}
7274

75+
/** Creates a LongRunningFunctionTool from a FunctionTool. */
76+
public static LongRunningFunctionTool create(FunctionTool tool) {
77+
return create(tool.instance(), tool.func(), tool.requireConfirmation());
78+
}
79+
7380
private LongRunningFunctionTool(Method func, boolean requireConfirmation) {
7481
super(null, func, /* isLongRunning= */ true, requireConfirmation);
7582
}
@@ -78,4 +85,25 @@ private LongRunningFunctionTool(
7885
@Nullable Object instance, Method func, boolean requireConfirmation) {
7986
super(instance, func, /* isLongRunning= */ true, requireConfirmation);
8087
}
88+
89+
public static LongRunningFunctionTool fromConfig(ToolArgsConfig config, String configAbsPath) {
90+
String funcName =
91+
config
92+
.getOrEmpty("func", new TypeReference<String>() {})
93+
.orElseThrow(
94+
() ->
95+
new IllegalArgumentException("\"func\" argument should be name of a function"));
96+
97+
FunctionTool funcTool =
98+
ComponentRegistry.getInstance()
99+
.get(funcName, FunctionTool.class)
100+
.orElseThrow(
101+
() ->
102+
new IllegalArgumentException(
103+
String.format(
104+
"failed to find FunctionTool \"%s\" in the ComponentRegistry",
105+
funcName)));
106+
107+
return create(funcTool);
108+
}
81109
}

core/src/main/java/com/google/adk/utils/ComponentRegistry.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.google.adk.tools.ExitLoopTool;
3333
import com.google.adk.tools.GoogleSearchTool;
3434
import com.google.adk.tools.LoadArtifactsTool;
35+
import com.google.adk.tools.LongRunningFunctionTool;
3536
import com.google.adk.tools.UrlContextTool;
3637
import com.google.adk.tools.mcp.McpToolset;
3738
import java.util.Map;
@@ -110,6 +111,7 @@ private void initializePreWiredEntries() {
110111
registerAdkToolInstance("url_context", UrlContextTool.INSTANCE);
111112

112113
registerAdkToolClass(AgentTool.class);
114+
registerAdkToolClass(LongRunningFunctionTool.class);
113115

114116
registerAdkToolsetClass(McpToolset.class);
115117
// TODO: add all python tools that also exist in Java.

core/src/test/java/com/google/adk/tools/LongRunningFunctionToolTest.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.google.adk.tools;
22

33
import static com.google.common.truth.Truth.assertThat;
4+
import static org.junit.Assert.assertThrows;
45

56
import com.google.adk.agents.LlmAgent;
67
import com.google.adk.artifacts.InMemoryArtifactService;
@@ -13,6 +14,8 @@
1314
import com.google.adk.sessions.InMemorySessionService;
1415
import com.google.adk.sessions.Session;
1516
import com.google.adk.testing.TestLlm;
17+
import com.google.adk.tools.BaseTool.ToolArgsConfig;
18+
import com.google.adk.utils.ComponentRegistry;
1619
import com.google.common.collect.ImmutableList;
1720
import com.google.common.collect.ImmutableMap;
1821
import com.google.errorprone.annotations.Keep;
@@ -92,6 +95,51 @@ public void asyncFunction_handlesPendingAndResults() throws Exception {
9295
assertThat(TestFunctions.functionCalledCount.get()).isEqualTo(1);
9396
}
9497

98+
@Test
99+
public void fromConfig_validConfig_createsTool() throws Exception {
100+
// Register a FunctionTool to be retrieved by fromConfig
101+
FunctionTool testTool =
102+
FunctionTool.create(
103+
null, TestFunctions.class.getMethod("increaseByOne", int.class, ToolContext.class));
104+
ComponentRegistry.getInstance().register("testFunc", testTool);
105+
106+
ToolArgsConfig config = new ToolArgsConfig();
107+
config.put("func", "testFunc");
108+
LongRunningFunctionTool longRunningTool =
109+
LongRunningFunctionTool.fromConfig(config, "testPath");
110+
111+
assertThat(longRunningTool).isNotNull();
112+
assertThat(longRunningTool.name()).isEqualTo("increase_by_one");
113+
}
114+
115+
@Test
116+
public void fromConfig_missingFunc_throwsException() {
117+
ToolArgsConfig config = new ToolArgsConfig();
118+
assertThrows(
119+
IllegalArgumentException.class,
120+
() -> LongRunningFunctionTool.fromConfig(config, "testPath"));
121+
}
122+
123+
@Test
124+
public void fromConfig_funcNotString_throwsException() {
125+
ToolArgsConfig config = new ToolArgsConfig();
126+
config.put("func", 123);
127+
assertThrows(
128+
IllegalArgumentException.class,
129+
() -> LongRunningFunctionTool.fromConfig(config, "testPath"));
130+
}
131+
132+
@Test
133+
public void fromConfig_funcNotFound_throwsException() {
134+
ToolArgsConfig config = new ToolArgsConfig();
135+
config.put("func", "nonExistentFunc");
136+
IllegalArgumentException exception =
137+
assertThrows(
138+
IllegalArgumentException.class,
139+
() -> LongRunningFunctionTool.fromConfig(config, "testPath"));
140+
assertThat(exception).hasMessageThat().contains("\"nonExistentFunc\"");
141+
}
142+
95143
private static class TestFunctions {
96144
static final AtomicInteger functionCalledCount = new AtomicInteger(0);
97145

0 commit comments

Comments
 (0)