google-adk 0.0.3__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.
- google/adk/agents/run_config.py +4 -0
- google/adk/auth/auth_preprocessor.py +19 -16
- google/adk/cli/browser/index.html +1 -1
- google/adk/cli/browser/{main-SY2WYYGV.js → main-CU22TRPI.js} +30 -30
- google/adk/cli/cli.py +8 -8
- google/adk/cli/cli_deploy.py +2 -4
- google/adk/cli/cli_tools_click.py +6 -6
- google/adk/flows/llm_flows/contents.py +21 -1
- google/adk/flows/llm_flows/functions.py +3 -1
- google/adk/models/google_llm.py +0 -1
- google/adk/runners.py +13 -2
- google/adk/version.py +1 -1
- {google_adk-0.0.3.dist-info → google_adk-0.0.4.dist-info}/METADATA +4 -2
- google_adk-0.0.4.dist-info/RECORD +175 -0
- {google_adk-0.0.3.dist-info → google_adk-0.0.4.dist-info}/WHEEL +1 -1
- google_adk-0.0.4.dist-info/licenses/LICENSE +202 -0
- google/adk/._version.py +0 -0
- google/adk/docs/Makefile +0 -20
- google/adk/docs/build/doctrees/google-adk.doctree +0 -0
- google/adk/docs/build/html/_sources/google-adk.rst.txt +0 -98
- google/adk/docs/build/html/_sources/index.rst.txt +0 -7
- google/adk/docs/build/html/_static/autodoc_pydantic.css +0 -27
- google/adk/docs/build/html/_static/basic.css +0 -925
- google/adk/docs/build/html/_static/debug.css +0 -85
- google/adk/docs/build/html/_static/doctools.js +0 -156
- google/adk/docs/build/html/_static/documentation_options.js +0 -29
- google/adk/docs/build/html/_static/file.png +0 -0
- google/adk/docs/build/html/_static/language_data.js +0 -199
- google/adk/docs/build/html/_static/minus.png +0 -0
- google/adk/docs/build/html/_static/plus.png +0 -0
- google/adk/docs/build/html/_static/pygments.css +0 -274
- google/adk/docs/build/html/_static/scripts/furo-extensions.js +0 -16
- google/adk/docs/build/html/_static/scripts/furo.js +0 -19
- google/adk/docs/build/html/_static/scripts/furo.js.LICENSE.txt +0 -7
- google/adk/docs/build/html/_static/scripts/furo.js.map +0 -1
- google/adk/docs/build/html/_static/searchtools.js +0 -620
- google/adk/docs/build/html/_static/skeleton.css +0 -312
- google/adk/docs/build/html/_static/sphinx_highlight.js +0 -170
- google/adk/docs/build/html/_static/styles/furo-extensions.css +0 -18
- google/adk/docs/build/html/_static/styles/furo-extensions.css.map +0 -1
- google/adk/docs/build/html/_static/styles/furo.css +0 -18
- google/adk/docs/build/html/_static/styles/furo.css.map +0 -1
- google/adk/docs/build/html/genindex.html +0 -861
- google/adk/docs/build/html/google-adk.html +0 -5461
- google/adk/docs/build/html/index.html +0 -567
- google/adk/docs/build/html/objects.inv +0 -0
- google/adk/docs/build/html/py-modindex.html +0 -373
- google/adk/docs/build/html/search.html +0 -333
- google/adk/docs/build/html/searchindex.js +0 -17
- google/adk/docs/source/conf.py +0 -133
- google/adk/docs/source/google-adk.rst +0 -98
- google/adk/docs/source/index.rst +0 -7
- google/adk/tests/__init__.py +0 -14
- google/adk/tests/integration/.env.example +0 -10
- google/adk/tests/integration/__init__.py +0 -18
- google/adk/tests/integration/conftest.py +0 -119
- google/adk/tests/integration/fixture/__init__.py +0 -14
- google/adk/tests/integration/fixture/agent_with_config/__init__.py +0 -15
- google/adk/tests/integration/fixture/agent_with_config/agent.py +0 -88
- google/adk/tests/integration/fixture/callback_agent/__init__.py +0 -15
- google/adk/tests/integration/fixture/callback_agent/agent.py +0 -105
- google/adk/tests/integration/fixture/context_update_test/OWNERS +0 -1
- google/adk/tests/integration/fixture/context_update_test/__init__.py +0 -15
- google/adk/tests/integration/fixture/context_update_test/agent.py +0 -43
- google/adk/tests/integration/fixture/context_update_test/successful_test.session.json +0 -582
- google/adk/tests/integration/fixture/context_variable_agent/__init__.py +0 -15
- google/adk/tests/integration/fixture/context_variable_agent/agent.py +0 -115
- google/adk/tests/integration/fixture/customer_support_ma/__init__.py +0 -15
- google/adk/tests/integration/fixture/customer_support_ma/agent.py +0 -172
- google/adk/tests/integration/fixture/ecommerce_customer_service_agent/__init__.py +0 -15
- google/adk/tests/integration/fixture/ecommerce_customer_service_agent/agent.py +0 -338
- google/adk/tests/integration/fixture/ecommerce_customer_service_agent/order_query.test.json +0 -69
- google/adk/tests/integration/fixture/ecommerce_customer_service_agent/test_config.json +0 -6
- google/adk/tests/integration/fixture/flow_complex_spark/__init__.py +0 -15
- google/adk/tests/integration/fixture/flow_complex_spark/agent.py +0 -182
- google/adk/tests/integration/fixture/flow_complex_spark/sample.session.json +0 -190
- google/adk/tests/integration/fixture/hello_world_agent/__init__.py +0 -15
- google/adk/tests/integration/fixture/hello_world_agent/agent.py +0 -95
- google/adk/tests/integration/fixture/hello_world_agent/roll_die.test.json +0 -24
- google/adk/tests/integration/fixture/hello_world_agent/test_config.json +0 -6
- google/adk/tests/integration/fixture/home_automation_agent/__init__.py +0 -15
- google/adk/tests/integration/fixture/home_automation_agent/agent.py +0 -304
- google/adk/tests/integration/fixture/home_automation_agent/simple_test.test.json +0 -5
- google/adk/tests/integration/fixture/home_automation_agent/simple_test2.test.json +0 -5
- google/adk/tests/integration/fixture/home_automation_agent/test_config.json +0 -5
- google/adk/tests/integration/fixture/home_automation_agent/test_files/dependent_tool_calls.test.json +0 -18
- google/adk/tests/integration/fixture/home_automation_agent/test_files/memorizing_past_events/eval_data.test.json +0 -17
- google/adk/tests/integration/fixture/home_automation_agent/test_files/memorizing_past_events/test_config.json +0 -6
- google/adk/tests/integration/fixture/home_automation_agent/test_files/simple_multi_turn_conversation.test.json +0 -18
- google/adk/tests/integration/fixture/home_automation_agent/test_files/simple_test.test.json +0 -17
- google/adk/tests/integration/fixture/home_automation_agent/test_files/simple_test2.test.json +0 -5
- google/adk/tests/integration/fixture/home_automation_agent/test_files/test_config.json +0 -5
- google/adk/tests/integration/fixture/tool_agent/__init__.py +0 -15
- google/adk/tests/integration/fixture/tool_agent/agent.py +0 -218
- google/adk/tests/integration/fixture/tool_agent/files/Agent_test_plan.pdf +0 -0
- google/adk/tests/integration/fixture/trip_planner_agent/__init__.py +0 -15
- google/adk/tests/integration/fixture/trip_planner_agent/agent.py +0 -110
- google/adk/tests/integration/fixture/trip_planner_agent/initial.session.json +0 -13
- google/adk/tests/integration/fixture/trip_planner_agent/test_config.json +0 -5
- google/adk/tests/integration/fixture/trip_planner_agent/test_files/initial.session.json +0 -13
- google/adk/tests/integration/fixture/trip_planner_agent/test_files/test_config.json +0 -5
- google/adk/tests/integration/fixture/trip_planner_agent/test_files/trip_inquiry_sub_agent.test.json +0 -7
- google/adk/tests/integration/fixture/trip_planner_agent/trip_inquiry.test.json +0 -19
- google/adk/tests/integration/models/__init__.py +0 -14
- google/adk/tests/integration/models/test_google_llm.py +0 -65
- google/adk/tests/integration/test_callback.py +0 -70
- google/adk/tests/integration/test_context_variable.py +0 -67
- google/adk/tests/integration/test_evalute_agent_in_fixture.py +0 -76
- google/adk/tests/integration/test_multi_agent.py +0 -28
- google/adk/tests/integration/test_multi_turn.py +0 -42
- google/adk/tests/integration/test_single_agent.py +0 -23
- google/adk/tests/integration/test_sub_agent.py +0 -26
- google/adk/tests/integration/test_system_instruction.py +0 -177
- google/adk/tests/integration/test_tools.py +0 -287
- google/adk/tests/integration/test_with_test_file.py +0 -34
- google/adk/tests/integration/tools/__init__.py +0 -14
- google/adk/tests/integration/utils/__init__.py +0 -16
- google/adk/tests/integration/utils/asserts.py +0 -75
- google/adk/tests/integration/utils/test_runner.py +0 -97
- google/adk/tests/unittests/__init__.py +0 -14
- google/adk/tests/unittests/agents/__init__.py +0 -14
- google/adk/tests/unittests/agents/test_base_agent.py +0 -407
- google/adk/tests/unittests/agents/test_langgraph_agent.py +0 -191
- google/adk/tests/unittests/agents/test_llm_agent_callbacks.py +0 -138
- google/adk/tests/unittests/agents/test_llm_agent_fields.py +0 -231
- google/adk/tests/unittests/agents/test_loop_agent.py +0 -136
- google/adk/tests/unittests/agents/test_parallel_agent.py +0 -92
- google/adk/tests/unittests/agents/test_sequential_agent.py +0 -114
- google/adk/tests/unittests/artifacts/__init__.py +0 -14
- google/adk/tests/unittests/artifacts/test_artifact_service.py +0 -276
- google/adk/tests/unittests/auth/test_auth_handler.py +0 -575
- google/adk/tests/unittests/conftest.py +0 -73
- google/adk/tests/unittests/fast_api/__init__.py +0 -14
- google/adk/tests/unittests/fast_api/test_fast_api.py +0 -269
- google/adk/tests/unittests/flows/__init__.py +0 -14
- google/adk/tests/unittests/flows/llm_flows/__init__.py +0 -14
- google/adk/tests/unittests/flows/llm_flows/_test_examples.py +0 -142
- google/adk/tests/unittests/flows/llm_flows/test_agent_transfer.py +0 -311
- google/adk/tests/unittests/flows/llm_flows/test_functions_long_running.py +0 -244
- google/adk/tests/unittests/flows/llm_flows/test_functions_request_euc.py +0 -346
- google/adk/tests/unittests/flows/llm_flows/test_functions_sequential.py +0 -93
- google/adk/tests/unittests/flows/llm_flows/test_functions_simple.py +0 -258
- google/adk/tests/unittests/flows/llm_flows/test_identity.py +0 -66
- google/adk/tests/unittests/flows/llm_flows/test_instructions.py +0 -164
- google/adk/tests/unittests/flows/llm_flows/test_model_callbacks.py +0 -142
- google/adk/tests/unittests/flows/llm_flows/test_other_configs.py +0 -46
- google/adk/tests/unittests/flows/llm_flows/test_tool_callbacks.py +0 -269
- google/adk/tests/unittests/models/__init__.py +0 -14
- google/adk/tests/unittests/models/test_google_llm.py +0 -224
- google/adk/tests/unittests/models/test_litellm.py +0 -804
- google/adk/tests/unittests/models/test_models.py +0 -60
- google/adk/tests/unittests/sessions/__init__.py +0 -14
- google/adk/tests/unittests/sessions/test_session_service.py +0 -227
- google/adk/tests/unittests/sessions/test_vertex_ai_session_service.py +0 -246
- google/adk/tests/unittests/streaming/__init__.py +0 -14
- google/adk/tests/unittests/streaming/test_streaming.py +0 -50
- google/adk/tests/unittests/tools/__init__.py +0 -14
- google/adk/tests/unittests/tools/apihub_tool/clients/test_apihub_client.py +0 -499
- google/adk/tests/unittests/tools/apihub_tool/test_apihub_toolset.py +0 -204
- google/adk/tests/unittests/tools/application_integration_tool/clients/test_connections_client.py +0 -600
- google/adk/tests/unittests/tools/application_integration_tool/clients/test_integration_client.py +0 -630
- google/adk/tests/unittests/tools/application_integration_tool/test_application_integration_toolset.py +0 -345
- google/adk/tests/unittests/tools/google_api_tool/__init__.py +0 -13
- google/adk/tests/unittests/tools/google_api_tool/test_googleapi_to_openapi_converter.py +0 -657
- google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_auto_auth_credential_exchanger.py +0 -145
- google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_base_auth_credential_exchanger.py +0 -68
- google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_oauth2_exchanger.py +0 -153
- google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_service_account_exchanger.py +0 -196
- google/adk/tests/unittests/tools/openapi_tool/auth/test_auth_helper.py +0 -573
- google/adk/tests/unittests/tools/openapi_tool/common/test_common.py +0 -436
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test.yaml +0 -1367
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_openapi_spec_parser.py +0 -628
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_openapi_toolset.py +0 -139
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_operation_parser.py +0 -406
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_rest_api_tool.py +0 -966
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_tool_auth_handler.py +0 -201
- google/adk/tests/unittests/tools/retrieval/__init__.py +0 -14
- google/adk/tests/unittests/tools/retrieval/test_vertex_ai_rag_retrieval.py +0 -147
- google/adk/tests/unittests/tools/test_agent_tool.py +0 -167
- google/adk/tests/unittests/tools/test_base_tool.py +0 -141
- google/adk/tests/unittests/tools/test_build_function_declaration.py +0 -277
- google/adk/tests/unittests/utils.py +0 -304
- google_adk-0.0.3.dist-info/RECORD +0 -340
- {google_adk-0.0.3.dist-info → google_adk-0.0.4.dist-info}/entry_points.txt +0 -0
@@ -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,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,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
|
-
)
|