google-adk 0.0.2__py3-none-any.whl → 0.0.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. google/adk/agents/run_config.py +4 -0
  2. google/adk/auth/auth_preprocessor.py +19 -16
  3. google/adk/cli/agent_graph.py +31 -5
  4. google/adk/cli/browser/index.html +1 -1
  5. google/adk/cli/browser/{main-XUU6OGCC.js → main-CU22TRPI.js} +30 -30
  6. google/adk/cli/cli.py +8 -8
  7. google/adk/cli/cli_deploy.py +2 -4
  8. google/adk/cli/cli_tools_click.py +57 -12
  9. google/adk/cli/fast_api.py +19 -9
  10. google/adk/flows/llm_flows/contents.py +21 -1
  11. google/adk/flows/llm_flows/functions.py +3 -1
  12. google/adk/models/google_llm.py +0 -1
  13. google/adk/runners.py +13 -2
  14. google/adk/version.py +1 -1
  15. {google_adk-0.0.2.dist-info → google_adk-0.0.4.dist-info}/METADATA +4 -2
  16. google_adk-0.0.4.dist-info/RECORD +175 -0
  17. {google_adk-0.0.2.dist-info → google_adk-0.0.4.dist-info}/WHEEL +1 -1
  18. google/adk/cli/media_streamer/__init__.py +0 -19
  19. google/adk/cli/media_streamer/index.html +0 -228
  20. google/adk/tests/__init__.py +0 -14
  21. google/adk/tests/integration/.env.example +0 -10
  22. google/adk/tests/integration/__init__.py +0 -18
  23. google/adk/tests/integration/conftest.py +0 -119
  24. google/adk/tests/integration/fixture/__init__.py +0 -14
  25. google/adk/tests/integration/fixture/agent_with_config/__init__.py +0 -15
  26. google/adk/tests/integration/fixture/agent_with_config/agent.py +0 -88
  27. google/adk/tests/integration/fixture/callback_agent/__init__.py +0 -15
  28. google/adk/tests/integration/fixture/callback_agent/agent.py +0 -105
  29. google/adk/tests/integration/fixture/context_update_test/OWNERS +0 -1
  30. google/adk/tests/integration/fixture/context_update_test/__init__.py +0 -15
  31. google/adk/tests/integration/fixture/context_update_test/agent.py +0 -43
  32. google/adk/tests/integration/fixture/context_update_test/successful_test.session.json +0 -582
  33. google/adk/tests/integration/fixture/context_variable_agent/__init__.py +0 -15
  34. google/adk/tests/integration/fixture/context_variable_agent/agent.py +0 -115
  35. google/adk/tests/integration/fixture/customer_support_ma/__init__.py +0 -15
  36. google/adk/tests/integration/fixture/customer_support_ma/agent.py +0 -172
  37. google/adk/tests/integration/fixture/ecommerce_customer_service_agent/__init__.py +0 -15
  38. google/adk/tests/integration/fixture/ecommerce_customer_service_agent/agent.py +0 -338
  39. google/adk/tests/integration/fixture/ecommerce_customer_service_agent/order_query.test.json +0 -69
  40. google/adk/tests/integration/fixture/ecommerce_customer_service_agent/test_config.json +0 -6
  41. google/adk/tests/integration/fixture/flow_complex_spark/__init__.py +0 -15
  42. google/adk/tests/integration/fixture/flow_complex_spark/agent.py +0 -182
  43. google/adk/tests/integration/fixture/flow_complex_spark/sample.debug.log +0 -243
  44. google/adk/tests/integration/fixture/flow_complex_spark/sample.session.json +0 -190
  45. google/adk/tests/integration/fixture/hello_world_agent/__init__.py +0 -15
  46. google/adk/tests/integration/fixture/hello_world_agent/agent.py +0 -95
  47. google/adk/tests/integration/fixture/hello_world_agent/roll_die.test.json +0 -24
  48. google/adk/tests/integration/fixture/hello_world_agent/test_config.json +0 -6
  49. google/adk/tests/integration/fixture/home_automation_agent/__init__.py +0 -15
  50. google/adk/tests/integration/fixture/home_automation_agent/agent.py +0 -304
  51. google/adk/tests/integration/fixture/home_automation_agent/simple_test.test.json +0 -5
  52. google/adk/tests/integration/fixture/home_automation_agent/simple_test2.test.json +0 -5
  53. google/adk/tests/integration/fixture/home_automation_agent/test_config.json +0 -5
  54. google/adk/tests/integration/fixture/home_automation_agent/test_files/dependent_tool_calls.test.json +0 -18
  55. google/adk/tests/integration/fixture/home_automation_agent/test_files/memorizing_past_events/eval_data.test.json +0 -17
  56. google/adk/tests/integration/fixture/home_automation_agent/test_files/memorizing_past_events/test_config.json +0 -6
  57. google/adk/tests/integration/fixture/home_automation_agent/test_files/simple_multi_turn_conversation.test.json +0 -18
  58. google/adk/tests/integration/fixture/home_automation_agent/test_files/simple_test.test.json +0 -17
  59. google/adk/tests/integration/fixture/home_automation_agent/test_files/simple_test2.test.json +0 -5
  60. google/adk/tests/integration/fixture/home_automation_agent/test_files/test_config.json +0 -5
  61. google/adk/tests/integration/fixture/tool_agent/__init__.py +0 -15
  62. google/adk/tests/integration/fixture/tool_agent/agent.py +0 -218
  63. google/adk/tests/integration/fixture/tool_agent/files/Agent_test_plan.pdf +0 -0
  64. google/adk/tests/integration/fixture/trip_planner_agent/__init__.py +0 -15
  65. google/adk/tests/integration/fixture/trip_planner_agent/agent.py +0 -110
  66. google/adk/tests/integration/fixture/trip_planner_agent/initial.session.json +0 -13
  67. google/adk/tests/integration/fixture/trip_planner_agent/test_config.json +0 -5
  68. google/adk/tests/integration/fixture/trip_planner_agent/test_files/initial.session.json +0 -13
  69. google/adk/tests/integration/fixture/trip_planner_agent/test_files/test_config.json +0 -5
  70. google/adk/tests/integration/fixture/trip_planner_agent/test_files/trip_inquiry_sub_agent.test.json +0 -7
  71. google/adk/tests/integration/fixture/trip_planner_agent/trip_inquiry.test.json +0 -19
  72. google/adk/tests/integration/models/__init__.py +0 -14
  73. google/adk/tests/integration/models/test_google_llm.py +0 -65
  74. google/adk/tests/integration/test_callback.py +0 -70
  75. google/adk/tests/integration/test_context_variable.py +0 -67
  76. google/adk/tests/integration/test_evalute_agent_in_fixture.py +0 -76
  77. google/adk/tests/integration/test_multi_agent.py +0 -28
  78. google/adk/tests/integration/test_multi_turn.py +0 -42
  79. google/adk/tests/integration/test_single_agent.py +0 -23
  80. google/adk/tests/integration/test_sub_agent.py +0 -26
  81. google/adk/tests/integration/test_system_instruction.py +0 -177
  82. google/adk/tests/integration/test_tools.py +0 -287
  83. google/adk/tests/integration/test_with_test_file.py +0 -34
  84. google/adk/tests/integration/tools/__init__.py +0 -14
  85. google/adk/tests/integration/utils/__init__.py +0 -16
  86. google/adk/tests/integration/utils/asserts.py +0 -75
  87. google/adk/tests/integration/utils/test_runner.py +0 -97
  88. google/adk/tests/unittests/__init__.py +0 -14
  89. google/adk/tests/unittests/agents/__init__.py +0 -14
  90. google/adk/tests/unittests/agents/test_base_agent.py +0 -407
  91. google/adk/tests/unittests/agents/test_langgraph_agent.py +0 -191
  92. google/adk/tests/unittests/agents/test_llm_agent_callbacks.py +0 -138
  93. google/adk/tests/unittests/agents/test_llm_agent_fields.py +0 -231
  94. google/adk/tests/unittests/agents/test_loop_agent.py +0 -136
  95. google/adk/tests/unittests/agents/test_parallel_agent.py +0 -92
  96. google/adk/tests/unittests/agents/test_sequential_agent.py +0 -114
  97. google/adk/tests/unittests/artifacts/__init__.py +0 -14
  98. google/adk/tests/unittests/artifacts/test_artifact_service.py +0 -276
  99. google/adk/tests/unittests/auth/test_auth_handler.py +0 -575
  100. google/adk/tests/unittests/conftest.py +0 -73
  101. google/adk/tests/unittests/fast_api/__init__.py +0 -14
  102. google/adk/tests/unittests/fast_api/test_fast_api.py +0 -269
  103. google/adk/tests/unittests/flows/__init__.py +0 -14
  104. google/adk/tests/unittests/flows/llm_flows/__init__.py +0 -14
  105. google/adk/tests/unittests/flows/llm_flows/_test_examples.py +0 -142
  106. google/adk/tests/unittests/flows/llm_flows/test_agent_transfer.py +0 -311
  107. google/adk/tests/unittests/flows/llm_flows/test_functions_long_running.py +0 -244
  108. google/adk/tests/unittests/flows/llm_flows/test_functions_request_euc.py +0 -346
  109. google/adk/tests/unittests/flows/llm_flows/test_functions_sequential.py +0 -93
  110. google/adk/tests/unittests/flows/llm_flows/test_functions_simple.py +0 -258
  111. google/adk/tests/unittests/flows/llm_flows/test_identity.py +0 -66
  112. google/adk/tests/unittests/flows/llm_flows/test_instructions.py +0 -164
  113. google/adk/tests/unittests/flows/llm_flows/test_model_callbacks.py +0 -142
  114. google/adk/tests/unittests/flows/llm_flows/test_other_configs.py +0 -46
  115. google/adk/tests/unittests/flows/llm_flows/test_tool_callbacks.py +0 -269
  116. google/adk/tests/unittests/models/__init__.py +0 -14
  117. google/adk/tests/unittests/models/test_google_llm.py +0 -224
  118. google/adk/tests/unittests/models/test_litellm.py +0 -804
  119. google/adk/tests/unittests/models/test_models.py +0 -60
  120. google/adk/tests/unittests/sessions/__init__.py +0 -14
  121. google/adk/tests/unittests/sessions/test_session_service.py +0 -227
  122. google/adk/tests/unittests/sessions/test_vertex_ai_session_service.py +0 -246
  123. google/adk/tests/unittests/streaming/__init__.py +0 -14
  124. google/adk/tests/unittests/streaming/test_streaming.py +0 -50
  125. google/adk/tests/unittests/tools/__init__.py +0 -14
  126. google/adk/tests/unittests/tools/apihub_tool/clients/test_apihub_client.py +0 -499
  127. google/adk/tests/unittests/tools/apihub_tool/test_apihub_toolset.py +0 -204
  128. google/adk/tests/unittests/tools/application_integration_tool/clients/test_connections_client.py +0 -600
  129. google/adk/tests/unittests/tools/application_integration_tool/clients/test_integration_client.py +0 -630
  130. google/adk/tests/unittests/tools/application_integration_tool/test_application_integration_toolset.py +0 -345
  131. google/adk/tests/unittests/tools/google_api_tool/__init__.py +0 -13
  132. google/adk/tests/unittests/tools/google_api_tool/test_googleapi_to_openapi_converter.py +0 -657
  133. google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_auto_auth_credential_exchanger.py +0 -145
  134. google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_base_auth_credential_exchanger.py +0 -68
  135. google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_oauth2_exchanger.py +0 -153
  136. google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_service_account_exchanger.py +0 -196
  137. google/adk/tests/unittests/tools/openapi_tool/auth/test_auth_helper.py +0 -573
  138. google/adk/tests/unittests/tools/openapi_tool/common/test_common.py +0 -436
  139. google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test.yaml +0 -1367
  140. google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_openapi_spec_parser.py +0 -628
  141. google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_openapi_toolset.py +0 -139
  142. google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_operation_parser.py +0 -406
  143. google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_rest_api_tool.py +0 -966
  144. google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_tool_auth_handler.py +0 -201
  145. google/adk/tests/unittests/tools/retrieval/__init__.py +0 -14
  146. google/adk/tests/unittests/tools/retrieval/test_vertex_ai_rag_retrieval.py +0 -147
  147. google/adk/tests/unittests/tools/test_agent_tool.py +0 -167
  148. google/adk/tests/unittests/tools/test_base_tool.py +0 -141
  149. google/adk/tests/unittests/tools/test_build_function_declaration.py +0 -277
  150. google/adk/tests/unittests/utils.py +0 -304
  151. google_adk-0.0.2.dist-info/RECORD +0 -308
  152. {google_adk-0.0.2.dist-info → google_adk-0.0.4.dist-info}/entry_points.txt +0 -0
  153. {google_adk-0.0.2.dist-info → google_adk-0.0.4.dist-info/licenses}/LICENSE +0 -0
@@ -1,201 +0,0 @@
1
- # Copyright 2025 Google LLC
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- from typing import Optional
16
- from unittest.mock import MagicMock
17
-
18
- from google.adk.agents.invocation_context import InvocationContext
19
- from google.adk.agents.llm_agent import LlmAgent
20
- from google.adk.auth.auth_credential import AuthCredential
21
- from google.adk.auth.auth_credential import AuthCredentialTypes
22
- from google.adk.auth.auth_credential import HttpAuth
23
- from google.adk.auth.auth_credential import HttpCredentials
24
- from google.adk.auth.auth_credential import OAuth2Auth
25
- from google.adk.auth.auth_schemes import AuthScheme
26
- from google.adk.sessions.in_memory_session_service import InMemorySessionService
27
- from google.adk.sessions.session import Session
28
- from google.adk.tools.openapi_tool.auth.auth_helpers import openid_dict_to_scheme_credential
29
- from google.adk.tools.openapi_tool.auth.auth_helpers import token_to_scheme_credential
30
- from google.adk.tools.openapi_tool.auth.credential_exchangers.auto_auth_credential_exchanger import OAuth2CredentialExchanger
31
- from google.adk.tools.openapi_tool.openapi_spec_parser.tool_auth_handler import ToolAuthHandler
32
- from google.adk.tools.openapi_tool.openapi_spec_parser.tool_auth_handler import ToolContextCredentialStore
33
- from google.adk.tools.tool_context import ToolContext
34
- import pytest
35
-
36
-
37
- # Helper function to create a mock ToolContext
38
- def create_mock_tool_context():
39
- return ToolContext(
40
- function_call_id='test-fc-id',
41
- invocation_context=InvocationContext(
42
- agent=LlmAgent(name='test'),
43
- session=Session(app_name='test', user_id='123', id='123'),
44
- invocation_id='123',
45
- session_service=InMemorySessionService(),
46
- ),
47
- )
48
-
49
-
50
- # Test cases for OpenID Connect
51
- class MockOpenIdConnectCredentialExchanger(OAuth2CredentialExchanger):
52
-
53
- def __init__(
54
- self, expected_scheme, expected_credential, expected_access_token
55
- ):
56
- self.expected_scheme = expected_scheme
57
- self.expected_credential = expected_credential
58
- self.expected_access_token = expected_access_token
59
-
60
- def exchange_credential(
61
- self,
62
- auth_scheme: AuthScheme,
63
- auth_credential: Optional[AuthCredential] = None,
64
- ) -> AuthCredential:
65
- if auth_credential.oauth2 and (
66
- auth_credential.oauth2.auth_response_uri
67
- or auth_credential.oauth2.auth_code
68
- ):
69
- auth_code = (
70
- auth_credential.oauth2.auth_response_uri
71
- if auth_credential.oauth2.auth_response_uri
72
- else auth_credential.oauth2.auth_code
73
- )
74
- # Simulate the token exchange
75
- updated_credential = AuthCredential(
76
- auth_type=AuthCredentialTypes.HTTP, # Store as a bearer token
77
- http=HttpAuth(
78
- scheme='bearer',
79
- credentials=HttpCredentials(
80
- token=auth_code + self.expected_access_token
81
- ),
82
- ),
83
- )
84
- return updated_credential
85
-
86
- # simulate the case of getting auth_uri
87
- return None
88
-
89
-
90
- def get_mock_openid_scheme_credential():
91
- config_dict = {
92
- 'authorization_endpoint': 'test.com',
93
- 'token_endpoint': 'test.com',
94
- }
95
- scopes = ['test_scope']
96
- credential_dict = {
97
- 'client_id': '123',
98
- 'client_secret': '456',
99
- 'redirect_uri': 'test.com',
100
- }
101
- return openid_dict_to_scheme_credential(config_dict, scopes, credential_dict)
102
-
103
-
104
- # Fixture for the OpenID Connect security scheme
105
- @pytest.fixture
106
- def openid_connect_scheme():
107
- scheme, _ = get_mock_openid_scheme_credential()
108
- return scheme
109
-
110
-
111
- # Fixture for a base OpenID Connect credential
112
- @pytest.fixture
113
- def openid_connect_credential():
114
- _, credential = get_mock_openid_scheme_credential()
115
- return credential
116
-
117
-
118
- def test_openid_connect_no_auth_response(
119
- openid_connect_scheme, openid_connect_credential
120
- ):
121
- # Setup Mock exchanger
122
- mock_exchanger = MockOpenIdConnectCredentialExchanger(
123
- openid_connect_scheme, openid_connect_credential, None
124
- )
125
- tool_context = create_mock_tool_context()
126
- credential_store = ToolContextCredentialStore(tool_context=tool_context)
127
- handler = ToolAuthHandler(
128
- tool_context,
129
- openid_connect_scheme,
130
- openid_connect_credential,
131
- credential_exchanger=mock_exchanger,
132
- credential_store=credential_store,
133
- )
134
- result = handler.prepare_auth_credentials()
135
- assert result.state == 'pending'
136
- assert result.auth_credential == openid_connect_credential
137
-
138
-
139
- def test_openid_connect_with_auth_response(
140
- openid_connect_scheme, openid_connect_credential, monkeypatch
141
- ):
142
- mock_exchanger = MockOpenIdConnectCredentialExchanger(
143
- openid_connect_scheme,
144
- openid_connect_credential,
145
- 'test_access_token',
146
- )
147
- tool_context = create_mock_tool_context()
148
-
149
- mock_auth_handler = MagicMock()
150
- mock_auth_handler.get_auth_response.return_value = AuthCredential(
151
- auth_type=AuthCredentialTypes.OPEN_ID_CONNECT,
152
- oauth2=OAuth2Auth(auth_response_uri='test_auth_response_uri'),
153
- )
154
- mock_auth_handler_path = 'google.adk.tools.tool_context.AuthHandler'
155
- monkeypatch.setattr(
156
- mock_auth_handler_path, lambda *args, **kwargs: mock_auth_handler
157
- )
158
-
159
- credential_store = ToolContextCredentialStore(tool_context=tool_context)
160
- handler = ToolAuthHandler(
161
- tool_context,
162
- openid_connect_scheme,
163
- openid_connect_credential,
164
- credential_exchanger=mock_exchanger,
165
- credential_store=credential_store,
166
- )
167
- result = handler.prepare_auth_credentials()
168
- assert result.state == 'done'
169
- assert result.auth_credential.auth_type == AuthCredentialTypes.HTTP
170
- assert 'test_access_token' in result.auth_credential.http.credentials.token
171
- # Verify that the credential was stored:
172
- stored_credential = credential_store.get_credential(
173
- openid_connect_scheme, openid_connect_credential
174
- )
175
- assert stored_credential == result.auth_credential
176
- mock_auth_handler.get_auth_response.assert_called_once()
177
-
178
-
179
- def test_openid_connect_existing_token(
180
- openid_connect_scheme, openid_connect_credential
181
- ):
182
- _, existing_credential = token_to_scheme_credential(
183
- 'oauth2Token', 'header', 'bearer', '123123123'
184
- )
185
- tool_context = create_mock_tool_context()
186
- # Store the credential to simulate existing credential
187
- credential_store = ToolContextCredentialStore(tool_context=tool_context)
188
- key = credential_store.get_credential_key(
189
- openid_connect_scheme, openid_connect_credential
190
- )
191
- credential_store.store_credential(key, existing_credential)
192
-
193
- handler = ToolAuthHandler(
194
- tool_context,
195
- openid_connect_scheme,
196
- openid_connect_credential,
197
- credential_store=credential_store,
198
- )
199
- result = handler.prepare_auth_credentials()
200
- assert result.state == 'done'
201
- assert result.auth_credential == existing_credential
@@ -1,14 +0,0 @@
1
- # Copyright 2025 Google LLC
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
@@ -1,147 +0,0 @@
1
- # Copyright 2025 Google LLC
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- from google.adk.agents import Agent
16
- from google.adk.tools.function_tool import FunctionTool
17
- from google.adk.tools.retrieval.vertex_ai_rag_retrieval import VertexAiRagRetrieval
18
- from google.genai import types
19
-
20
- from ... import utils
21
-
22
-
23
- def noop_tool(x: str) -> str:
24
- return x
25
-
26
-
27
- def test_vertex_rag_retrieval_for_gemini_1_x():
28
- responses = [
29
- 'response1',
30
- ]
31
- mockModel = utils.MockModel.create(responses=responses)
32
- mockModel.model = 'gemini-1.5-pro'
33
-
34
- # Calls the first time.
35
- agent = Agent(
36
- name='root_agent',
37
- model=mockModel,
38
- tools=[
39
- VertexAiRagRetrieval(
40
- name='rag_retrieval',
41
- description='rag_retrieval',
42
- rag_corpora=[
43
- 'projects/123456789/locations/us-central1/ragCorpora/1234567890'
44
- ],
45
- )
46
- ],
47
- )
48
- runner = utils.InMemoryRunner(agent)
49
- events = runner.run('test1')
50
-
51
- # Asserts the requests.
52
- assert len(mockModel.requests) == 1
53
- assert utils.simplify_contents(mockModel.requests[0].contents) == [
54
- ('user', 'test1'),
55
- ]
56
- assert len(mockModel.requests[0].config.tools) == 1
57
- assert (
58
- mockModel.requests[0].config.tools[0].function_declarations[0].name
59
- == 'rag_retrieval'
60
- )
61
- assert mockModel.requests[0].tools_dict['rag_retrieval'] is not None
62
-
63
-
64
- def test_vertex_rag_retrieval_for_gemini_1_x_with_another_function_tool():
65
- responses = [
66
- 'response1',
67
- ]
68
- mockModel = utils.MockModel.create(responses=responses)
69
- mockModel.model = 'gemini-1.5-pro'
70
-
71
- # Calls the first time.
72
- agent = Agent(
73
- name='root_agent',
74
- model=mockModel,
75
- tools=[
76
- VertexAiRagRetrieval(
77
- name='rag_retrieval',
78
- description='rag_retrieval',
79
- rag_corpora=[
80
- 'projects/123456789/locations/us-central1/ragCorpora/1234567890'
81
- ],
82
- ),
83
- FunctionTool(func=noop_tool),
84
- ],
85
- )
86
- runner = utils.InMemoryRunner(agent)
87
- events = runner.run('test1')
88
-
89
- # Asserts the requests.
90
- assert len(mockModel.requests) == 1
91
- assert utils.simplify_contents(mockModel.requests[0].contents) == [
92
- ('user', 'test1'),
93
- ]
94
- assert len(mockModel.requests[0].config.tools[0].function_declarations) == 2
95
- assert (
96
- mockModel.requests[0].config.tools[0].function_declarations[0].name
97
- == 'rag_retrieval'
98
- )
99
- assert (
100
- mockModel.requests[0].config.tools[0].function_declarations[1].name
101
- == 'noop_tool'
102
- )
103
- assert mockModel.requests[0].tools_dict['rag_retrieval'] is not None
104
-
105
-
106
- def test_vertex_rag_retrieval_for_gemini_2_x():
107
- responses = [
108
- 'response1',
109
- ]
110
- mockModel = utils.MockModel.create(responses=responses)
111
- mockModel.model = 'gemini-2.0-flash'
112
-
113
- # Calls the first time.
114
- agent = Agent(
115
- name='root_agent',
116
- model=mockModel,
117
- tools=[
118
- VertexAiRagRetrieval(
119
- name='rag_retrieval',
120
- description='rag_retrieval',
121
- rag_corpora=[
122
- 'projects/123456789/locations/us-central1/ragCorpora/1234567890'
123
- ],
124
- )
125
- ],
126
- )
127
- runner = utils.InMemoryRunner(agent)
128
- events = runner.run('test1')
129
-
130
- # Asserts the requests.
131
- assert len(mockModel.requests) == 1
132
- assert utils.simplify_contents(mockModel.requests[0].contents) == [
133
- ('user', 'test1'),
134
- ]
135
- assert len(mockModel.requests[0].config.tools) == 1
136
- assert mockModel.requests[0].config.tools == [
137
- types.Tool(
138
- retrieval=types.Retrieval(
139
- vertex_rag_store=types.VertexRagStore(
140
- rag_corpora=[
141
- 'projects/123456789/locations/us-central1/ragCorpora/1234567890'
142
- ]
143
- )
144
- )
145
- )
146
- ]
147
- assert 'rag_retrieval' not in mockModel.requests[0].tools_dict
@@ -1,167 +0,0 @@
1
- # Copyright 2025 Google LLC
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- from google.adk.agents import Agent
16
- from google.adk.agents.callback_context import CallbackContext
17
- from google.adk.tools.agent_tool import AgentTool
18
- from google.genai.types import Part
19
- from pydantic import BaseModel
20
- import pytest
21
- from pytest import mark
22
-
23
- from .. import utils
24
-
25
- pytestmark = pytest.mark.skip(
26
- reason='Skipping until tool.func evaluations are fixed (async)'
27
- )
28
-
29
-
30
- function_call_custom = Part.from_function_call(
31
- name='tool_agent', args={'custom_input': 'test1'}
32
- )
33
-
34
- function_call_no_schema = Part.from_function_call(
35
- name='tool_agent', args={'request': 'test1'}
36
- )
37
-
38
- function_response_custom = Part.from_function_response(
39
- name='tool_agent', response={'custom_output': 'response1'}
40
- )
41
-
42
- function_response_no_schema = Part.from_function_response(
43
- name='tool_agent', response={'result': 'response1'}
44
- )
45
-
46
-
47
- def change_state_callback(callback_context: CallbackContext):
48
- callback_context.state['state_1'] = 'changed_value'
49
- print('change_state_callback: ', callback_context.state)
50
-
51
-
52
- def test_no_schema():
53
- mock_model = utils.MockModel.create(
54
- responses=[
55
- function_call_no_schema,
56
- 'response1',
57
- 'response2',
58
- ]
59
- )
60
-
61
- tool_agent = Agent(
62
- name='tool_agent',
63
- model=mock_model,
64
- )
65
-
66
- root_agent = Agent(
67
- name='root_agent',
68
- model=mock_model,
69
- tools=[AgentTool(agent=tool_agent)],
70
- )
71
-
72
- runner = utils.InMemoryRunner(root_agent)
73
-
74
- assert utils.simplify_events(runner.run('test1')) == [
75
- ('root_agent', function_call_no_schema),
76
- ('root_agent', function_response_no_schema),
77
- ('root_agent', 'response2'),
78
- ]
79
-
80
-
81
- def test_update_state():
82
- """The agent tool can read and change parent state."""
83
-
84
- mock_model = utils.MockModel.create(
85
- responses=[
86
- function_call_no_schema,
87
- '{"custom_output": "response1"}',
88
- 'response2',
89
- ]
90
- )
91
-
92
- tool_agent = Agent(
93
- name='tool_agent',
94
- model=mock_model,
95
- instruction='input: {state_1}',
96
- before_agent_callback=change_state_callback,
97
- )
98
-
99
- root_agent = Agent(
100
- name='root_agent',
101
- model=mock_model,
102
- tools=[AgentTool(agent=tool_agent)],
103
- )
104
-
105
- runner = utils.InMemoryRunner(root_agent)
106
- runner.session.state['state_1'] = 'state1_value'
107
-
108
- runner.run('test1')
109
- assert (
110
- 'input: changed_value' in mock_model.requests[1].config.system_instruction
111
- )
112
- assert runner.session.state['state_1'] == 'changed_value'
113
-
114
-
115
- @mark.parametrize(
116
- 'env_variables',
117
- [
118
- 'GOOGLE_AI',
119
- # TODO(wanyif): re-enable after fix.
120
- # 'VERTEX',
121
- ],
122
- indirect=True,
123
- )
124
- def test_custom_schema():
125
- class CustomInput(BaseModel):
126
- custom_input: str
127
-
128
- class CustomOutput(BaseModel):
129
- custom_output: str
130
-
131
- mock_model = utils.MockModel.create(
132
- responses=[
133
- function_call_custom,
134
- '{"custom_output": "response1"}',
135
- 'response2',
136
- ]
137
- )
138
-
139
- tool_agent = Agent(
140
- name='tool_agent',
141
- model=mock_model,
142
- input_schema=CustomInput,
143
- output_schema=CustomOutput,
144
- output_key='tool_output',
145
- )
146
-
147
- root_agent = Agent(
148
- name='root_agent',
149
- model=mock_model,
150
- tools=[AgentTool(agent=tool_agent)],
151
- )
152
-
153
- runner = utils.InMemoryRunner(root_agent)
154
- runner.session.state['state_1'] = 'state1_value'
155
-
156
- assert utils.simplify_events(runner.run('test1')) == [
157
- ('root_agent', function_call_custom),
158
- ('root_agent', function_response_custom),
159
- ('root_agent', 'response2'),
160
- ]
161
-
162
- assert runner.session.state['tool_output'] == {'custom_output': 'response1'}
163
-
164
- assert len(mock_model.requests) == 3
165
- # The second request is the tool agent request.
166
- assert mock_model.requests[1].config.response_schema == CustomOutput
167
- assert mock_model.requests[1].config.response_mime_type == 'application/json'
@@ -1,141 +0,0 @@
1
- # Copyright 2025 Google LLC
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- from typing import Optional
16
-
17
- from google.adk.agents.invocation_context import InvocationContext
18
- from google.adk.agents.sequential_agent import SequentialAgent
19
- from google.adk.models.llm_request import LlmRequest
20
- from google.adk.sessions.in_memory_session_service import InMemorySessionService
21
- from google.adk.tools.base_tool import BaseTool
22
- from google.adk.tools.tool_context import ToolContext
23
- from google.genai import types
24
- import pytest
25
-
26
-
27
- class _TestingTool(BaseTool):
28
-
29
- def __init__(
30
- self,
31
- declaration: Optional[types.FunctionDeclaration] = None,
32
- ):
33
- super().__init__(name='test_tool', description='test_description')
34
- self.declaration = declaration
35
-
36
- def _get_declaration(self) -> Optional[types.FunctionDeclaration]:
37
- return self.declaration
38
-
39
-
40
- def _create_tool_context() -> ToolContext:
41
- session_service = InMemorySessionService()
42
- session = session_service.create_session(
43
- app_name='test_app', user_id='test_user'
44
- )
45
- agent = SequentialAgent(name='test_agent')
46
- invocation_context = InvocationContext(
47
- invocation_id='invocation_id',
48
- agent=agent,
49
- session=session,
50
- session_service=session_service,
51
- )
52
- return ToolContext(invocation_context)
53
-
54
-
55
- @pytest.mark.asyncio
56
- async def test_process_llm_request_no_declaration():
57
- tool = _TestingTool()
58
- tool_context = _create_tool_context()
59
- llm_request = LlmRequest()
60
-
61
- await tool.process_llm_request(
62
- tool_context=tool_context, llm_request=llm_request
63
- )
64
-
65
- assert llm_request.config is None
66
-
67
-
68
- @pytest.mark.asyncio
69
- async def test_process_llm_request_with_declaration():
70
- declaration = types.FunctionDeclaration(
71
- name='test_tool',
72
- description='test_description',
73
- parameters=types.Schema(
74
- type=types.Type.STRING,
75
- title='param_1',
76
- ),
77
- )
78
- tool = _TestingTool(declaration)
79
- llm_request = LlmRequest()
80
- tool_context = _create_tool_context()
81
-
82
- await tool.process_llm_request(
83
- tool_context=tool_context, llm_request=llm_request
84
- )
85
-
86
- assert llm_request.config.tools[0].function_declarations == [declaration]
87
-
88
-
89
- @pytest.mark.asyncio
90
- async def test_process_llm_request_with_builtin_tool():
91
- declaration = types.FunctionDeclaration(
92
- name='test_tool',
93
- description='test_description',
94
- parameters=types.Schema(
95
- type=types.Type.STRING,
96
- title='param_1',
97
- ),
98
- )
99
- tool = _TestingTool(declaration)
100
- llm_request = LlmRequest(
101
- config=types.GenerateContentConfig(
102
- tools=[types.Tool(google_search=types.GoogleSearch())]
103
- )
104
- )
105
- tool_context = _create_tool_context()
106
-
107
- await tool.process_llm_request(
108
- tool_context=tool_context, llm_request=llm_request
109
- )
110
-
111
- # function_declaration is added to another types.Tool without builtin tool.
112
- assert llm_request.config.tools[1].function_declarations == [declaration]
113
-
114
-
115
- @pytest.mark.asyncio
116
- async def test_process_llm_request_with_builtin_tool_and_another_declaration():
117
- declaration = types.FunctionDeclaration(
118
- name='test_tool',
119
- description='test_description',
120
- parameters=types.Schema(
121
- type=types.Type.STRING,
122
- title='param_1',
123
- ),
124
- )
125
- tool = _TestingTool(declaration)
126
- llm_request = LlmRequest(
127
- config=types.GenerateContentConfig(
128
- tools=[
129
- types.Tool(google_search=types.GoogleSearch()),
130
- types.Tool(function_declarations=[types.FunctionDeclaration()]),
131
- ]
132
- )
133
- )
134
- tool_context = _create_tool_context()
135
-
136
- await tool.process_llm_request(
137
- tool_context=tool_context, llm_request=llm_request
138
- )
139
-
140
- # function_declaration is added to existing types.Tool with function_declaration.
141
- assert llm_request.config.tools[1].function_declarations[1] == declaration