|
34 | 34 | import com.google.common.collect.ImmutableList; |
35 | 35 | import com.google.common.collect.ImmutableMap; |
36 | 36 | import com.google.genai.types.Content; |
| 37 | +import com.google.genai.types.FunctionCall; |
37 | 38 | import com.google.genai.types.FunctionDeclaration; |
38 | 39 | import com.google.genai.types.Part; |
39 | 40 | import com.google.genai.types.Schema; |
@@ -72,8 +73,29 @@ public Single<Map<String, Object>> runAsync(Map<String, Object> args, ToolContex |
72 | 73 | } |
73 | 74 | } |
74 | 75 |
|
| 76 | + private static class NormalTool extends BaseTool { |
| 77 | + NormalTool() { |
| 78 | + super("normal_tool", "Normal tool."); |
| 79 | + } |
| 80 | + |
| 81 | + @Override |
| 82 | + public Optional<FunctionDeclaration> declaration() { |
| 83 | + return Optional.of( |
| 84 | + FunctionDeclaration.builder() |
| 85 | + .name(name()) |
| 86 | + .description(description()) |
| 87 | + .parameters(Schema.builder().type("OBJECT").build()) |
| 88 | + .build()); |
| 89 | + } |
| 90 | + |
| 91 | + @Override |
| 92 | + public Single<Map<String, Object>> runAsync(Map<String, Object> args, ToolContext toolContext) { |
| 93 | + return Single.just(ImmutableMap.of("result", "success")); |
| 94 | + } |
| 95 | + } |
| 96 | + |
75 | 97 | @Test |
76 | | - public void toolRequestConfirmation_eventHasNonNullId() { |
| 98 | + public void toolRequestConfirmation_generatesConfirmationEvent() { |
77 | 99 | Content requestConfirmationCallContent = |
78 | 100 | Content.fromParts(Part.fromFunctionCall("request_confirmation_tool", ImmutableMap.of())); |
79 | 101 | Content response1 = Content.fromParts(Part.fromText("response1")); |
@@ -107,7 +129,51 @@ public void toolRequestConfirmation_eventHasNonNullId() { |
107 | 129 | .collect(toImmutableList()); |
108 | 130 |
|
109 | 131 | assertThat(confirmationEvents).isNotEmpty(); |
110 | | - assertThat(confirmationEvents.get(0).id()).isNotNull(); |
| 132 | + |
| 133 | + Event confirmationEvent = confirmationEvents.get(0); |
| 134 | + assertThat(confirmationEvent.id()).isNotNull(); |
| 135 | + |
| 136 | + FunctionCall functionCall = confirmationEvent.functionCalls().get(0); |
| 137 | + assertThat(functionCall.args()).isPresent(); |
| 138 | + |
| 139 | + Map<String, Object> args = functionCall.args().get(); |
| 140 | + assertThat(args).containsKey("toolConfirmation"); |
| 141 | + assertThat(args).containsKey("originalFunctionCall"); |
| 142 | + } |
| 143 | + |
| 144 | + @Test |
| 145 | + public void normalTool_doesNotGenerateConfirmationEvent() { |
| 146 | + Content normalCallContent = |
| 147 | + Content.fromParts(Part.fromFunctionCall("normal_tool", ImmutableMap.of())); |
| 148 | + Content response1 = Content.fromParts(Part.fromText("response1")); |
| 149 | + |
| 150 | + var testLlm = |
| 151 | + createTestLlm( |
| 152 | + Flowable.just(createLlmResponse(normalCallContent)), |
| 153 | + Flowable.just(createLlmResponse(response1))); |
| 154 | + |
| 155 | + LlmAgent rootAgent = |
| 156 | + createTestAgentBuilder(testLlm) |
| 157 | + .name("root_agent") |
| 158 | + .tools(ImmutableList.of(new NormalTool())) |
| 159 | + .build(); |
| 160 | + InvocationContext invocationContext = createInvocationContext(rootAgent); |
| 161 | + |
| 162 | + Runner runner = getRunnerAndCreateSession(rootAgent, invocationContext.session()); |
| 163 | + |
| 164 | + ImmutableList<Event> confirmationEvents = |
| 165 | + runRunner(runner, invocationContext).stream() |
| 166 | + .filter( |
| 167 | + e -> |
| 168 | + e.functionCalls().stream() |
| 169 | + .anyMatch( |
| 170 | + f -> |
| 171 | + Objects.equals( |
| 172 | + f.name().orElse(""), |
| 173 | + Functions.REQUEST_CONFIRMATION_FUNCTION_CALL_NAME))) |
| 174 | + .collect(toImmutableList()); |
| 175 | + |
| 176 | + assertThat(confirmationEvents).isEmpty(); |
111 | 177 | } |
112 | 178 |
|
113 | 179 | private Runner getRunnerAndCreateSession(LlmAgent agent, Session session) { |
|
0 commit comments