|
26 | 26 | import static com.google.common.collect.Iterables.getOnlyElement; |
27 | 27 | import static com.google.common.truth.Truth.assertThat; |
28 | 28 | import static org.junit.Assert.assertEquals; |
29 | | -import static org.junit.Assert.assertThrows; |
30 | 29 |
|
31 | 30 | import com.google.adk.agents.Callbacks.AfterModelCallback; |
32 | 31 | import com.google.adk.agents.Callbacks.AfterToolCallback; |
|
52 | 51 | import com.google.common.collect.ImmutableMap; |
53 | 52 | import com.google.errorprone.annotations.CanIgnoreReturnValue; |
54 | 53 | import com.google.genai.types.Content; |
55 | | -import com.google.genai.types.FunctionDeclaration; |
56 | 54 | import com.google.genai.types.Part; |
57 | 55 | import com.google.genai.types.Schema; |
| 56 | +import com.google.genai.types.Type; |
58 | 57 | import io.opentelemetry.api.trace.Span; |
59 | 58 | import io.opentelemetry.api.trace.Tracer; |
60 | 59 | import io.opentelemetry.sdk.testing.junit4.OpenTelemetryRule; |
|
63 | 62 | import io.reactivex.rxjava3.core.Maybe; |
64 | 63 | import io.reactivex.rxjava3.core.Single; |
65 | 64 | import java.util.List; |
66 | | -import java.util.Optional; |
67 | 65 | import java.util.concurrent.ConcurrentHashMap; |
68 | 66 | import java.util.concurrent.atomic.AtomicBoolean; |
69 | 67 | import org.junit.After; |
@@ -213,75 +211,6 @@ public void run_withToolsAndMaxSteps_stopsAfterMaxSteps() { |
213 | 211 | assertEqualIgnoringFunctionIds(events.get(3).content().get(), expectedFunctionResponseContent); |
214 | 212 | } |
215 | 213 |
|
216 | | - @Test |
217 | | - public void build_withOutputSchemaAndTools_throwsIllegalArgumentException() { |
218 | | - BaseTool tool = |
219 | | - new BaseTool("test_tool", "test_description") { |
220 | | - @Override |
221 | | - public Optional<FunctionDeclaration> declaration() { |
222 | | - return Optional.empty(); |
223 | | - } |
224 | | - }; |
225 | | - |
226 | | - Schema outputSchema = |
227 | | - Schema.builder() |
228 | | - .type("OBJECT") |
229 | | - .properties(ImmutableMap.of("status", Schema.builder().type("STRING").build())) |
230 | | - .required(ImmutableList.of("status")) |
231 | | - .build(); |
232 | | - |
233 | | - // Expecting an IllegalArgumentException when building the agent |
234 | | - IllegalArgumentException exception = |
235 | | - assertThrows( |
236 | | - IllegalArgumentException.class, |
237 | | - () -> |
238 | | - LlmAgent.builder() // Use the agent builder directly |
239 | | - .name("agent with invalid tool config") |
240 | | - .outputSchema(outputSchema) // Set the output schema |
241 | | - .tools(ImmutableList.of(tool)) // Set tools (this should cause the error) |
242 | | - .build()); // Attempt to build the agent |
243 | | - |
244 | | - assertThat(exception) |
245 | | - .hasMessageThat() |
246 | | - .contains( |
247 | | - "Invalid config for agent agent with invalid tool config: if outputSchema is set, tools" |
248 | | - + " must be empty"); |
249 | | - } |
250 | | - |
251 | | - @Test |
252 | | - public void build_withOutputSchemaAndSubAgents_throwsIllegalArgumentException() { |
253 | | - ImmutableList<BaseAgent> subAgents = |
254 | | - ImmutableList.of( |
255 | | - createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())) |
256 | | - .name("test_sub_agent") |
257 | | - .description("test_sub_agent_description") |
258 | | - .build()); |
259 | | - |
260 | | - Schema outputSchema = |
261 | | - Schema.builder() |
262 | | - .type("OBJECT") |
263 | | - .properties(ImmutableMap.of("status", Schema.builder().type("STRING").build())) |
264 | | - .required(ImmutableList.of("status")) |
265 | | - .build(); |
266 | | - |
267 | | - // Expecting an IllegalArgumentException when building the agent |
268 | | - IllegalArgumentException exception = |
269 | | - assertThrows( |
270 | | - IllegalArgumentException.class, |
271 | | - () -> |
272 | | - LlmAgent.builder() // Use the agent builder directly |
273 | | - .name("agent with invalid tool config") |
274 | | - .outputSchema(outputSchema) // Set the output schema |
275 | | - .subAgents(subAgents) // Set subAgents (this should cause the error) |
276 | | - .build()); // Attempt to build the agent |
277 | | - |
278 | | - assertThat(exception) |
279 | | - .hasMessageThat() |
280 | | - .contains( |
281 | | - "Invalid config for agent agent with invalid tool config: if outputSchema is set," |
282 | | - + " subAgents must be empty to disable agent transfer."); |
283 | | - } |
284 | | - |
285 | 214 | @Test |
286 | 215 | public void testBuild_withNullInstruction_setsInstructionToEmptyString() { |
287 | 216 | LlmAgent agent = |
@@ -645,6 +574,31 @@ public void runAsync_withSubAgents_createsSpans() throws InterruptedException { |
645 | 574 | assertThat(llmSpans).hasSize(2); // One for main agent, one for sub agent |
646 | 575 | } |
647 | 576 |
|
| 577 | + @Test |
| 578 | + public void run_outputSchemaWithTools_allowed() { |
| 579 | + Schema personShema = |
| 580 | + Schema.builder() |
| 581 | + .type(Type.Known.OBJECT) |
| 582 | + .properties( |
| 583 | + ImmutableMap.of( |
| 584 | + "name", Schema.builder().type(Type.Known.STRING).build(), |
| 585 | + "age", Schema.builder().type(Type.Known.INTEGER).build(), |
| 586 | + "city", Schema.builder().type(Type.Known.STRING).build())) |
| 587 | + .build(); |
| 588 | + LlmAgent agent = |
| 589 | + createTestAgentBuilder(createTestLlm(LlmResponse.builder().build())) |
| 590 | + .outputSchema(personShema) |
| 591 | + .tools(new EchoTool()) |
| 592 | + .build(); |
| 593 | + assertThat(agent.outputSchema()).hasValue(personShema); |
| 594 | + assertThat( |
| 595 | + agent |
| 596 | + .canonicalTools(new ReadonlyContext(createInvocationContext(agent))) |
| 597 | + .count() |
| 598 | + .blockingGet()) |
| 599 | + .isEqualTo(1); |
| 600 | + } |
| 601 | + |
648 | 602 | private List<SpanData> findSpansByName(List<SpanData> spans, String name) { |
649 | 603 | return spans.stream().filter(s -> s.getName().equals(name)).toList(); |
650 | 604 | } |
|
0 commit comments