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,407 +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
- """Testings for the BaseAgent."""
16
-
17
- from typing import AsyncGenerator
18
- from typing import Optional
19
- from typing import Union
20
-
21
- from google.adk.agents.base_agent import BaseAgent
22
- from google.adk.agents.callback_context import CallbackContext
23
- from google.adk.agents.invocation_context import InvocationContext
24
- from google.adk.events import Event
25
- from google.adk.sessions.in_memory_session_service import InMemorySessionService
26
- from google.genai import types
27
- import pytest
28
- import pytest_mock
29
- from typing_extensions import override
30
-
31
-
32
- def _before_agent_callback_noop(callback_context: CallbackContext) -> None:
33
- pass
34
-
35
-
36
- def _before_agent_callback_bypass_agent(
37
- callback_context: CallbackContext,
38
- ) -> types.Content:
39
- return types.Content(parts=[types.Part(text='agent run is bypassed.')])
40
-
41
-
42
- def _after_agent_callback_noop(callback_context: CallbackContext) -> None:
43
- pass
44
-
45
-
46
- def _after_agent_callback_append_agent_reply(
47
- callback_context: CallbackContext,
48
- ) -> types.Content:
49
- return types.Content(
50
- parts=[types.Part(text='Agent reply from after agent callback.')]
51
- )
52
-
53
-
54
- class _IncompleteAgent(BaseAgent):
55
- pass
56
-
57
-
58
- class _TestingAgent(BaseAgent):
59
-
60
- @override
61
- async def _run_async_impl(
62
- self, ctx: InvocationContext
63
- ) -> AsyncGenerator[Event, None]:
64
- yield Event(
65
- author=self.name,
66
- branch=ctx.branch,
67
- invocation_id=ctx.invocation_id,
68
- content=types.Content(parts=[types.Part(text='Hello, world!')]),
69
- )
70
-
71
- @override
72
- async def _run_live_impl(
73
- self, ctx: InvocationContext
74
- ) -> AsyncGenerator[Event, None]:
75
- yield Event(
76
- author=self.name,
77
- invocation_id=ctx.invocation_id,
78
- branch=ctx.branch,
79
- content=types.Content(parts=[types.Part(text='Hello, live!')]),
80
- )
81
-
82
-
83
- def _create_parent_invocation_context(
84
- test_name: str, agent: BaseAgent, branch: Optional[str] = None
85
- ) -> InvocationContext:
86
- session_service = InMemorySessionService()
87
- session = session_service.create_session(
88
- app_name='test_app', user_id='test_user'
89
- )
90
- return InvocationContext(
91
- invocation_id=f'{test_name}_invocation_id',
92
- branch=branch,
93
- agent=agent,
94
- session=session,
95
- session_service=session_service,
96
- )
97
-
98
-
99
- def test_invalid_agent_name():
100
- with pytest.raises(ValueError):
101
- _ = _TestingAgent(name='not an identifier')
102
-
103
-
104
- @pytest.mark.asyncio
105
- async def test_run_async(request: pytest.FixtureRequest):
106
- agent = _TestingAgent(name=f'{request.function.__name__}_test_agent')
107
- parent_ctx = _create_parent_invocation_context(
108
- request.function.__name__, agent
109
- )
110
-
111
- events = [e async for e in agent.run_async(parent_ctx)]
112
-
113
- assert len(events) == 1
114
- assert events[0].author == agent.name
115
- assert events[0].content.parts[0].text == 'Hello, world!'
116
-
117
-
118
- @pytest.mark.asyncio
119
- async def test_run_async_with_branch(request: pytest.FixtureRequest):
120
- agent = _TestingAgent(name=f'{request.function.__name__}_test_agent')
121
- parent_ctx = _create_parent_invocation_context(
122
- request.function.__name__, agent, branch='parent_branch'
123
- )
124
-
125
- events = [e async for e in agent.run_async(parent_ctx)]
126
-
127
- assert len(events) == 1
128
- assert events[0].author == agent.name
129
- assert events[0].content.parts[0].text == 'Hello, world!'
130
- assert events[0].branch.endswith(agent.name)
131
-
132
-
133
- @pytest.mark.asyncio
134
- async def test_run_async_before_agent_callback_noop(
135
- request: pytest.FixtureRequest,
136
- mocker: pytest_mock.MockerFixture,
137
- ) -> Union[types.Content, None]:
138
- # Arrange
139
- agent = _TestingAgent(
140
- name=f'{request.function.__name__}_test_agent',
141
- before_agent_callback=_before_agent_callback_noop,
142
- )
143
- parent_ctx = _create_parent_invocation_context(
144
- request.function.__name__, agent
145
- )
146
- spy_run_async_impl = mocker.spy(agent, BaseAgent._run_async_impl.__name__)
147
- spy_before_agent_callback = mocker.spy(agent, 'before_agent_callback')
148
-
149
- # Act
150
- _ = [e async for e in agent.run_async(parent_ctx)]
151
-
152
- # Assert
153
- spy_before_agent_callback.assert_called_once()
154
- _, kwargs = spy_before_agent_callback.call_args
155
- assert 'callback_context' in kwargs
156
- assert isinstance(kwargs['callback_context'], CallbackContext)
157
-
158
- spy_run_async_impl.assert_called_once()
159
-
160
-
161
- @pytest.mark.asyncio
162
- async def test_run_async_before_agent_callback_bypass_agent(
163
- request: pytest.FixtureRequest,
164
- mocker: pytest_mock.MockerFixture,
165
- ):
166
- # Arrange
167
- agent = _TestingAgent(
168
- name=f'{request.function.__name__}_test_agent',
169
- before_agent_callback=_before_agent_callback_bypass_agent,
170
- )
171
- parent_ctx = _create_parent_invocation_context(
172
- request.function.__name__, agent
173
- )
174
- spy_run_async_impl = mocker.spy(agent, BaseAgent._run_async_impl.__name__)
175
- spy_before_agent_callback = mocker.spy(agent, 'before_agent_callback')
176
-
177
- # Act
178
- events = [e async for e in agent.run_async(parent_ctx)]
179
-
180
- # Assert
181
- spy_before_agent_callback.assert_called_once()
182
- spy_run_async_impl.assert_not_called()
183
-
184
- assert len(events) == 1
185
- assert events[0].content.parts[0].text == 'agent run is bypassed.'
186
-
187
-
188
- @pytest.mark.asyncio
189
- async def test_run_async_after_agent_callback_noop(
190
- request: pytest.FixtureRequest,
191
- mocker: pytest_mock.MockerFixture,
192
- ):
193
- # Arrange
194
- agent = _TestingAgent(
195
- name=f'{request.function.__name__}_test_agent',
196
- after_agent_callback=_after_agent_callback_noop,
197
- )
198
- parent_ctx = _create_parent_invocation_context(
199
- request.function.__name__, agent
200
- )
201
- spy_after_agent_callback = mocker.spy(agent, 'after_agent_callback')
202
-
203
- # Act
204
- events = [e async for e in agent.run_async(parent_ctx)]
205
-
206
- # Assert
207
- spy_after_agent_callback.assert_called_once()
208
- _, kwargs = spy_after_agent_callback.call_args
209
- assert 'callback_context' in kwargs
210
- assert isinstance(kwargs['callback_context'], CallbackContext)
211
- assert len(events) == 1
212
-
213
-
214
- @pytest.mark.asyncio
215
- async def test_run_async_after_agent_callback_append_reply(
216
- request: pytest.FixtureRequest,
217
- ):
218
- # Arrange
219
- agent = _TestingAgent(
220
- name=f'{request.function.__name__}_test_agent',
221
- after_agent_callback=_after_agent_callback_append_agent_reply,
222
- )
223
- parent_ctx = _create_parent_invocation_context(
224
- request.function.__name__, agent
225
- )
226
-
227
- # Act
228
- events = [e async for e in agent.run_async(parent_ctx)]
229
-
230
- # Assert
231
- assert len(events) == 2
232
- assert events[1].author == agent.name
233
- assert (
234
- events[1].content.parts[0].text
235
- == 'Agent reply from after agent callback.'
236
- )
237
-
238
-
239
- @pytest.mark.asyncio
240
- async def test_run_async_incomplete_agent(request: pytest.FixtureRequest):
241
- agent = _IncompleteAgent(name=f'{request.function.__name__}_test_agent')
242
- parent_ctx = _create_parent_invocation_context(
243
- request.function.__name__, agent
244
- )
245
-
246
- with pytest.raises(NotImplementedError):
247
- [e async for e in agent.run_async(parent_ctx)]
248
-
249
-
250
- @pytest.mark.asyncio
251
- async def test_run_live(request: pytest.FixtureRequest):
252
- agent = _TestingAgent(name=f'{request.function.__name__}_test_agent')
253
- parent_ctx = _create_parent_invocation_context(
254
- request.function.__name__, agent
255
- )
256
-
257
- events = [e async for e in agent.run_live(parent_ctx)]
258
-
259
- assert len(events) == 1
260
- assert events[0].author == agent.name
261
- assert events[0].content.parts[0].text == 'Hello, live!'
262
-
263
-
264
- @pytest.mark.asyncio
265
- async def test_run_live_with_branch(request: pytest.FixtureRequest):
266
- agent = _TestingAgent(name=f'{request.function.__name__}_test_agent')
267
- parent_ctx = _create_parent_invocation_context(
268
- request.function.__name__, agent, branch='parent_branch'
269
- )
270
-
271
- events = [e async for e in agent.run_live(parent_ctx)]
272
-
273
- assert len(events) == 1
274
- assert events[0].author == agent.name
275
- assert events[0].content.parts[0].text == 'Hello, live!'
276
- assert events[0].branch.endswith(agent.name)
277
-
278
-
279
- @pytest.mark.asyncio
280
- async def test_run_live_incomplete_agent(request: pytest.FixtureRequest):
281
- agent = _IncompleteAgent(name=f'{request.function.__name__}_test_agent')
282
- parent_ctx = _create_parent_invocation_context(
283
- request.function.__name__, agent
284
- )
285
-
286
- with pytest.raises(NotImplementedError):
287
- [e async for e in agent.run_live(parent_ctx)]
288
-
289
-
290
- def test_set_parent_agent_for_sub_agents(request: pytest.FixtureRequest):
291
- sub_agents: list[BaseAgent] = [
292
- _TestingAgent(name=f'{request.function.__name__}_sub_agent_1'),
293
- _TestingAgent(name=f'{request.function.__name__}_sub_agent_2'),
294
- ]
295
- parent = _TestingAgent(
296
- name=f'{request.function.__name__}_parent',
297
- sub_agents=sub_agents,
298
- )
299
-
300
- for sub_agent in sub_agents:
301
- assert sub_agent.parent_agent == parent
302
-
303
-
304
- def test_find_agent(request: pytest.FixtureRequest):
305
- grand_sub_agent_1 = _TestingAgent(
306
- name=f'{request.function.__name__}__grand_sub_agent_1'
307
- )
308
- grand_sub_agent_2 = _TestingAgent(
309
- name=f'{request.function.__name__}__grand_sub_agent_2'
310
- )
311
- sub_agent_1 = _TestingAgent(
312
- name=f'{request.function.__name__}_sub_agent_1',
313
- sub_agents=[grand_sub_agent_1],
314
- )
315
- sub_agent_2 = _TestingAgent(
316
- name=f'{request.function.__name__}_sub_agent_2',
317
- sub_agents=[grand_sub_agent_2],
318
- )
319
- parent = _TestingAgent(
320
- name=f'{request.function.__name__}_parent',
321
- sub_agents=[sub_agent_1, sub_agent_2],
322
- )
323
-
324
- assert parent.find_agent(parent.name) == parent
325
- assert parent.find_agent(sub_agent_1.name) == sub_agent_1
326
- assert parent.find_agent(sub_agent_2.name) == sub_agent_2
327
- assert parent.find_agent(grand_sub_agent_1.name) == grand_sub_agent_1
328
- assert parent.find_agent(grand_sub_agent_2.name) == grand_sub_agent_2
329
- assert sub_agent_1.find_agent(grand_sub_agent_1.name) == grand_sub_agent_1
330
- assert sub_agent_1.find_agent(grand_sub_agent_2.name) is None
331
- assert sub_agent_2.find_agent(grand_sub_agent_1.name) is None
332
- assert sub_agent_2.find_agent(sub_agent_2.name) == sub_agent_2
333
- assert parent.find_agent('not_exist') is None
334
-
335
-
336
- def test_find_sub_agent(request: pytest.FixtureRequest):
337
- grand_sub_agent_1 = _TestingAgent(
338
- name=f'{request.function.__name__}__grand_sub_agent_1'
339
- )
340
- grand_sub_agent_2 = _TestingAgent(
341
- name=f'{request.function.__name__}__grand_sub_agent_2'
342
- )
343
- sub_agent_1 = _TestingAgent(
344
- name=f'{request.function.__name__}_sub_agent_1',
345
- sub_agents=[grand_sub_agent_1],
346
- )
347
- sub_agent_2 = _TestingAgent(
348
- name=f'{request.function.__name__}_sub_agent_2',
349
- sub_agents=[grand_sub_agent_2],
350
- )
351
- parent = _TestingAgent(
352
- name=f'{request.function.__name__}_parent',
353
- sub_agents=[sub_agent_1, sub_agent_2],
354
- )
355
-
356
- assert parent.find_sub_agent(sub_agent_1.name) == sub_agent_1
357
- assert parent.find_sub_agent(sub_agent_2.name) == sub_agent_2
358
- assert parent.find_sub_agent(grand_sub_agent_1.name) == grand_sub_agent_1
359
- assert parent.find_sub_agent(grand_sub_agent_2.name) == grand_sub_agent_2
360
- assert sub_agent_1.find_sub_agent(grand_sub_agent_1.name) == grand_sub_agent_1
361
- assert sub_agent_1.find_sub_agent(grand_sub_agent_2.name) is None
362
- assert sub_agent_2.find_sub_agent(grand_sub_agent_1.name) is None
363
- assert sub_agent_2.find_sub_agent(grand_sub_agent_2.name) == grand_sub_agent_2
364
- assert parent.find_sub_agent(parent.name) is None
365
- assert parent.find_sub_agent('not_exist') is None
366
-
367
-
368
- def test_root_agent(request: pytest.FixtureRequest):
369
- grand_sub_agent_1 = _TestingAgent(
370
- name=f'{request.function.__name__}__grand_sub_agent_1'
371
- )
372
- grand_sub_agent_2 = _TestingAgent(
373
- name=f'{request.function.__name__}__grand_sub_agent_2'
374
- )
375
- sub_agent_1 = _TestingAgent(
376
- name=f'{request.function.__name__}_sub_agent_1',
377
- sub_agents=[grand_sub_agent_1],
378
- )
379
- sub_agent_2 = _TestingAgent(
380
- name=f'{request.function.__name__}_sub_agent_2',
381
- sub_agents=[grand_sub_agent_2],
382
- )
383
- parent = _TestingAgent(
384
- name=f'{request.function.__name__}_parent',
385
- sub_agents=[sub_agent_1, sub_agent_2],
386
- )
387
-
388
- assert parent.root_agent == parent
389
- assert sub_agent_1.root_agent == parent
390
- assert sub_agent_2.root_agent == parent
391
- assert grand_sub_agent_1.root_agent == parent
392
- assert grand_sub_agent_2.root_agent == parent
393
-
394
-
395
- def test_set_parent_agent_for_sub_agent_twice(
396
- request: pytest.FixtureRequest,
397
- ):
398
- sub_agent = _TestingAgent(name=f'{request.function.__name__}_sub_agent')
399
- _ = _TestingAgent(
400
- name=f'{request.function.__name__}_parent_1',
401
- sub_agents=[sub_agent],
402
- )
403
- with pytest.raises(ValueError):
404
- _ = _TestingAgent(
405
- name=f'{request.function.__name__}_parent_2',
406
- sub_agents=[sub_agent],
407
- )
@@ -1,191 +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 unittest.mock import MagicMock
16
-
17
- from google.adk.agents.invocation_context import InvocationContext
18
- from google.adk.agents.langgraph_agent import LangGraphAgent
19
- from google.adk.events import Event
20
- from google.genai import types
21
- from langchain_core.messages import AIMessage
22
- from langchain_core.messages import HumanMessage
23
- from langchain_core.messages import SystemMessage
24
- from langgraph.graph.graph import CompiledGraph
25
- import pytest
26
-
27
-
28
- @pytest.mark.parametrize(
29
- "checkpointer_value, events_list, expected_messages",
30
- [
31
- (
32
- MagicMock(),
33
- [
34
- Event(
35
- invocation_id="test_invocation_id",
36
- author="user",
37
- content=types.Content(
38
- role="user",
39
- parts=[types.Part.from_text(text="test prompt")],
40
- ),
41
- ),
42
- Event(
43
- invocation_id="test_invocation_id",
44
- author="root_agent",
45
- content=types.Content(
46
- role="model",
47
- parts=[types.Part.from_text(text="(some delegation)")],
48
- ),
49
- ),
50
- ],
51
- [
52
- SystemMessage(content="test system prompt"),
53
- HumanMessage(content="test prompt"),
54
- ],
55
- ),
56
- (
57
- None,
58
- [
59
- Event(
60
- invocation_id="test_invocation_id",
61
- author="user",
62
- content=types.Content(
63
- role="user",
64
- parts=[types.Part.from_text(text="user prompt 1")],
65
- ),
66
- ),
67
- Event(
68
- invocation_id="test_invocation_id",
69
- author="root_agent",
70
- content=types.Content(
71
- role="model",
72
- parts=[
73
- types.Part.from_text(text="root agent response")
74
- ],
75
- ),
76
- ),
77
- Event(
78
- invocation_id="test_invocation_id",
79
- author="weather_agent",
80
- content=types.Content(
81
- role="model",
82
- parts=[
83
- types.Part.from_text(text="weather agent response")
84
- ],
85
- ),
86
- ),
87
- Event(
88
- invocation_id="test_invocation_id",
89
- author="user",
90
- content=types.Content(
91
- role="user",
92
- parts=[types.Part.from_text(text="user prompt 2")],
93
- ),
94
- ),
95
- ],
96
- [
97
- SystemMessage(content="test system prompt"),
98
- HumanMessage(content="user prompt 1"),
99
- AIMessage(content="weather agent response"),
100
- HumanMessage(content="user prompt 2"),
101
- ],
102
- ),
103
- (
104
- MagicMock(),
105
- [
106
- Event(
107
- invocation_id="test_invocation_id",
108
- author="user",
109
- content=types.Content(
110
- role="user",
111
- parts=[types.Part.from_text(text="user prompt 1")],
112
- ),
113
- ),
114
- Event(
115
- invocation_id="test_invocation_id",
116
- author="root_agent",
117
- content=types.Content(
118
- role="model",
119
- parts=[
120
- types.Part.from_text(text="root agent response")
121
- ],
122
- ),
123
- ),
124
- Event(
125
- invocation_id="test_invocation_id",
126
- author="weather_agent",
127
- content=types.Content(
128
- role="model",
129
- parts=[
130
- types.Part.from_text(text="weather agent response")
131
- ],
132
- ),
133
- ),
134
- Event(
135
- invocation_id="test_invocation_id",
136
- author="user",
137
- content=types.Content(
138
- role="user",
139
- parts=[types.Part.from_text(text="user prompt 2")],
140
- ),
141
- ),
142
- ],
143
- [
144
- SystemMessage(content="test system prompt"),
145
- HumanMessage(content="user prompt 2"),
146
- ],
147
- ),
148
- ],
149
- )
150
- @pytest.mark.asyncio
151
- async def test_langgraph_agent(
152
- checkpointer_value, events_list, expected_messages
153
- ):
154
- mock_graph = MagicMock(spec=CompiledGraph)
155
- mock_graph_state = MagicMock()
156
- mock_graph_state.values = {}
157
- mock_graph.get_state.return_value = mock_graph_state
158
-
159
- mock_graph.checkpointer = checkpointer_value
160
- mock_graph.invoke.return_value = {
161
- "messages": [AIMessage(content="test response")]
162
- }
163
-
164
- mock_parent_context = MagicMock(spec=InvocationContext)
165
- mock_session = MagicMock()
166
- mock_parent_context.session = mock_session
167
- mock_parent_context.branch = "parent_agent"
168
- mock_parent_context.end_invocation = False
169
- mock_session.events = events_list
170
- mock_parent_context.invocation_id = "test_invocation_id"
171
- mock_parent_context.model_copy.return_value = mock_parent_context
172
-
173
- weather_agent = LangGraphAgent(
174
- name="weather_agent",
175
- description="A agent that answers weather questions",
176
- instruction="test system prompt",
177
- graph=mock_graph,
178
- )
179
-
180
- result_event = None
181
- async for event in weather_agent.run_async(mock_parent_context):
182
- result_event = event
183
-
184
- assert result_event.author == "weather_agent"
185
- assert result_event.content.parts[0].text == "test response"
186
-
187
- mock_graph.invoke.assert_called_once()
188
- mock_graph.invoke.assert_called_with(
189
- {"messages": expected_messages},
190
- {"configurable": {"thread_id": mock_session.id}},
191
- )