google-adk 1.0.0__py3-none-any.whl → 1.1.1__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 (94) hide show
  1. google/adk/agents/callback_context.py +2 -1
  2. google/adk/agents/readonly_context.py +3 -1
  3. google/adk/auth/auth_credential.py +4 -1
  4. google/adk/cli/browser/index.html +4 -4
  5. google/adk/cli/browser/{main-QOEMUXM4.js → main-PKDNKWJE.js} +59 -59
  6. google/adk/cli/browser/polyfills-B6TNHZQ6.js +17 -0
  7. google/adk/cli/cli.py +3 -2
  8. google/adk/cli/cli_eval.py +6 -85
  9. google/adk/cli/cli_tools_click.py +39 -10
  10. google/adk/cli/fast_api.py +53 -184
  11. google/adk/cli/utils/agent_loader.py +137 -0
  12. google/adk/cli/utils/cleanup.py +40 -0
  13. google/adk/cli/utils/evals.py +2 -1
  14. google/adk/cli/utils/logs.py +2 -7
  15. google/adk/code_executors/code_execution_utils.py +2 -1
  16. google/adk/code_executors/container_code_executor.py +0 -1
  17. google/adk/code_executors/vertex_ai_code_executor.py +6 -8
  18. google/adk/evaluation/eval_case.py +3 -1
  19. google/adk/evaluation/eval_metrics.py +74 -0
  20. google/adk/evaluation/eval_result.py +86 -0
  21. google/adk/evaluation/eval_set.py +2 -0
  22. google/adk/evaluation/eval_set_results_manager.py +47 -0
  23. google/adk/evaluation/eval_sets_manager.py +2 -1
  24. google/adk/evaluation/evaluator.py +2 -0
  25. google/adk/evaluation/local_eval_set_results_manager.py +113 -0
  26. google/adk/evaluation/local_eval_sets_manager.py +4 -4
  27. google/adk/evaluation/response_evaluator.py +2 -1
  28. google/adk/evaluation/trajectory_evaluator.py +3 -2
  29. google/adk/examples/base_example_provider.py +1 -0
  30. google/adk/flows/llm_flows/base_llm_flow.py +4 -6
  31. google/adk/flows/llm_flows/contents.py +3 -1
  32. google/adk/flows/llm_flows/instructions.py +7 -77
  33. google/adk/flows/llm_flows/single_flow.py +1 -1
  34. google/adk/models/base_llm.py +2 -1
  35. google/adk/models/base_llm_connection.py +2 -0
  36. google/adk/models/google_llm.py +4 -1
  37. google/adk/models/lite_llm.py +3 -2
  38. google/adk/models/llm_response.py +2 -1
  39. google/adk/runners.py +36 -4
  40. google/adk/sessions/_session_util.py +2 -1
  41. google/adk/sessions/database_session_service.py +5 -8
  42. google/adk/sessions/vertex_ai_session_service.py +28 -13
  43. google/adk/telemetry.py +4 -2
  44. google/adk/tools/agent_tool.py +1 -1
  45. google/adk/tools/apihub_tool/apihub_toolset.py +1 -1
  46. google/adk/tools/apihub_tool/clients/apihub_client.py +10 -3
  47. google/adk/tools/apihub_tool/clients/secret_client.py +1 -0
  48. google/adk/tools/application_integration_tool/application_integration_toolset.py +6 -2
  49. google/adk/tools/application_integration_tool/clients/connections_client.py +8 -1
  50. google/adk/tools/application_integration_tool/clients/integration_client.py +3 -1
  51. google/adk/tools/application_integration_tool/integration_connector_tool.py +1 -1
  52. google/adk/tools/base_toolset.py +40 -2
  53. google/adk/tools/bigquery/__init__.py +38 -0
  54. google/adk/tools/bigquery/bigquery_credentials.py +217 -0
  55. google/adk/tools/bigquery/bigquery_tool.py +116 -0
  56. google/adk/tools/bigquery/bigquery_toolset.py +86 -0
  57. google/adk/tools/bigquery/client.py +33 -0
  58. google/adk/tools/bigquery/metadata_tool.py +249 -0
  59. google/adk/tools/bigquery/query_tool.py +76 -0
  60. google/adk/tools/function_parameter_parse_util.py +7 -0
  61. google/adk/tools/function_tool.py +33 -3
  62. google/adk/tools/get_user_choice_tool.py +1 -0
  63. google/adk/tools/google_api_tool/__init__.py +17 -11
  64. google/adk/tools/google_api_tool/google_api_tool.py +1 -1
  65. google/adk/tools/google_api_tool/google_api_toolset.py +0 -14
  66. google/adk/tools/google_api_tool/google_api_toolsets.py +8 -2
  67. google/adk/tools/google_search_tool.py +2 -2
  68. google/adk/tools/mcp_tool/conversion_utils.py +6 -2
  69. google/adk/tools/mcp_tool/mcp_session_manager.py +62 -188
  70. google/adk/tools/mcp_tool/mcp_tool.py +27 -24
  71. google/adk/tools/mcp_tool/mcp_toolset.py +76 -131
  72. google/adk/tools/openapi_tool/auth/credential_exchangers/base_credential_exchanger.py +1 -3
  73. google/adk/tools/openapi_tool/auth/credential_exchangers/service_account_exchanger.py +6 -7
  74. google/adk/tools/openapi_tool/common/common.py +5 -1
  75. google/adk/tools/openapi_tool/openapi_spec_parser/__init__.py +7 -2
  76. google/adk/tools/openapi_tool/openapi_spec_parser/openapi_toolset.py +2 -7
  77. google/adk/tools/openapi_tool/openapi_spec_parser/operation_parser.py +5 -1
  78. google/adk/tools/openapi_tool/openapi_spec_parser/rest_api_tool.py +11 -1
  79. google/adk/tools/toolbox_toolset.py +31 -3
  80. google/adk/utils/__init__.py +13 -0
  81. google/adk/utils/instructions_utils.py +131 -0
  82. google/adk/version.py +1 -1
  83. {google_adk-1.0.0.dist-info → google_adk-1.1.1.dist-info}/METADATA +12 -15
  84. {google_adk-1.0.0.dist-info → google_adk-1.1.1.dist-info}/RECORD +87 -78
  85. google/adk/agents/base_agent.py.orig +0 -330
  86. google/adk/cli/browser/polyfills-FFHMD2TL.js +0 -18
  87. google/adk/cli/fast_api.py.orig +0 -822
  88. google/adk/memory/base_memory_service.py.orig +0 -76
  89. google/adk/models/google_llm.py.orig +0 -305
  90. google/adk/tools/_built_in_code_execution_tool.py +0 -70
  91. google/adk/tools/mcp_tool/mcp_session_manager.py.orig +0 -322
  92. {google_adk-1.0.0.dist-info → google_adk-1.1.1.dist-info}/WHEEL +0 -0
  93. {google_adk-1.0.0.dist-info → google_adk-1.1.1.dist-info}/entry_points.txt +0 -0
  94. {google_adk-1.0.0.dist-info → google_adk-1.1.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,76 +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
- import abc
16
-
17
- from pydantic import BaseModel
18
- from pydantic import Field
19
-
20
- from ..events.event import Event
21
- from ..sessions.session import Session
22
-
23
-
24
- class MemoryResult(BaseModel):
25
- """Represents a single memory retrieval result.
26
-
27
- Attributes:
28
- session_id: The session id associated with the memory.
29
- events: A list of events in the session.
30
- """
31
-
32
- session_id: str
33
- events: list[Event]
34
-
35
-
36
- class SearchMemoryResponse(BaseModel):
37
- """Represents the response from a memory search.
38
-
39
- Attributes:
40
- memories: A list of memory results matching the search query.
41
- """
42
-
43
- memories: list[MemoryResult] = Field(default_factory=list)
44
-
45
-
46
- class BaseMemoryService(abc.ABC):
47
- """Base class for memory services.
48
-
49
- The service provides functionalities to ingest sessions into memory so that
50
- the memory can be used for user queries.
51
- """
52
-
53
- @abc.abstractmethod
54
- async def add_session_to_memory(self, session: Session):
55
- """Adds a session to the memory service.
56
-
57
- A session may be added multiple times during its lifetime.
58
-
59
- Args:
60
- session: The session to add.
61
- """
62
-
63
- @abc.abstractmethod
64
- async def search_memory(
65
- self, *, app_name: str, user_id: str, query: str
66
- ) -> SearchMemoryResponse:
67
- """Searches for sessions that match the query.
68
-
69
- Args:
70
- app_name: The name of the application.
71
- user_id: The id of the user.
72
- query: The query to search for.
73
-
74
- Returns:
75
- A SearchMemoryResponse containing the matching memories.
76
- """
@@ -1,305 +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
- from __future__ import annotations
15
-
16
- import contextlib
17
- from functools import cached_property
18
- import logging
19
- import sys
20
- from typing import AsyncGenerator
21
- from typing import cast
22
- from typing import TYPE_CHECKING
23
-
24
- from google.genai import Client
25
- from google.genai import types
26
- from typing_extensions import override
27
-
28
- from .. import version
29
- from .base_llm import BaseLlm
30
- from .base_llm_connection import BaseLlmConnection
31
- from .gemini_llm_connection import GeminiLlmConnection
32
- from .llm_response import LlmResponse
33
-
34
- if TYPE_CHECKING:
35
- from .llm_request import LlmRequest
36
-
37
- logger = None
38
-
39
- _NEW_LINE = '\n'
40
- _EXCLUDED_PART_FIELD = {'inline_data': {'data'}}
41
-
42
-
43
- class Gemini(BaseLlm):
44
- """Integration for Gemini models.
45
-
46
- Attributes:
47
- model: The name of the Gemini model.
48
- """
49
-
50
- model: str = 'gemini-1.5-flash'
51
-
52
- @staticmethod
53
- @override
54
- def supported_models() -> list[str]:
55
- """Provides the list of supported models.
56
-
57
- Returns:
58
- A list of supported models.
59
- """
60
-
61
- return [
62
- r'gemini-.*',
63
- # fine-tuned vertex endpoint pattern
64
- r'projects\/.+\/locations\/.+\/endpoints\/.+',
65
- # vertex gemini long name
66
- r'projects\/.+\/locations\/.+\/publishers\/google\/models\/gemini.+',
67
- ]
68
-
69
- async def generate_content_async(
70
- self, llm_request: LlmRequest, stream: bool = False
71
- ) -> AsyncGenerator[LlmResponse, None]:
72
- """Sends a request to the Gemini model.
73
-
74
- Args:
75
- llm_request: LlmRequest, the request to send to the Gemini model.
76
- stream: bool = False, whether to do streaming call.
77
-
78
- Yields:
79
- LlmResponse: The model response.
80
- """
81
-
82
- self._maybe_append_user_content(llm_request)
83
-
84
- global logger
85
- if not logger:
86
- logger = logging.getLogger(__name__)
87
-
88
- logger.info(
89
- 'Sending out request, model: %s, backend: %s, stream: %s',
90
- llm_request.model,
91
- self._api_backend,
92
- stream,
93
- )
94
- logger.info(_build_request_log(llm_request))
95
-
96
- print('********* Jack --> ')
97
- for hh in logging.root.handlers:
98
- print(hh, hh.level)
99
- for hh in logger.handlers:
100
- print(hh, hh.level)
101
- print('********* Jack <-- ')
102
-
103
- if stream:
104
- responses = await self.api_client.aio.models.generate_content_stream(
105
- model=llm_request.model,
106
- contents=llm_request.contents,
107
- config=llm_request.config,
108
- )
109
- response = None
110
- text = ''
111
- # for sse, similar as bidi (see receive method in gemini_llm_connecton.py),
112
- # we need to mark those text content as partial and after all partial
113
- # contents are sent, we send an accumulated event which contains all the
114
- # previous partial content. The only difference is bidi rely on
115
- # complete_turn flag to detect end while sse depends on finish_reason.
116
- async for response in responses:
117
- logger.info(_build_response_log(response))
118
- llm_response = LlmResponse.create(response)
119
- if (
120
- llm_response.content
121
- and llm_response.content.parts
122
- and llm_response.content.parts[0].text
123
- ):
124
- text += llm_response.content.parts[0].text
125
- llm_response.partial = True
126
- elif text and (
127
- not llm_response.content
128
- or not llm_response.content.parts
129
- # don't yield the merged text event when receiving audio data
130
- or not llm_response.content.parts[0].inline_data
131
- ):
132
- yield LlmResponse(
133
- content=types.ModelContent(
134
- parts=[types.Part.from_text(text=text)],
135
- ),
136
- usage_metadata=llm_response.usage_metadata,
137
- )
138
- text = ''
139
- yield llm_response
140
- if (
141
- text
142
- and response
143
- and response.candidates
144
- and response.candidates[0].finish_reason == types.FinishReason.STOP
145
- ):
146
- yield LlmResponse(
147
- content=types.ModelContent(
148
- parts=[types.Part.from_text(text=text)],
149
- ),
150
- )
151
-
152
- else:
153
- response = await self.api_client.aio.models.generate_content(
154
- model=llm_request.model,
155
- contents=llm_request.contents,
156
- config=llm_request.config,
157
- )
158
- logger.info(_build_response_log(response))
159
- yield LlmResponse.create(response)
160
-
161
- @cached_property
162
- def api_client(self) -> Client:
163
- """Provides the api client.
164
-
165
- Returns:
166
- The api client.
167
- """
168
- return Client(
169
- http_options=types.HttpOptions(headers=self._tracking_headers)
170
- )
171
-
172
- @cached_property
173
- def _api_backend(self) -> str:
174
- return 'vertex' if self.api_client.vertexai else 'ml_dev'
175
-
176
- @cached_property
177
- def _tracking_headers(self) -> dict[str, str]:
178
- framework_label = f'google-adk/{version.__version__}'
179
- language_label = 'gl-python/' + sys.version.split()[0]
180
- version_header_value = f'{framework_label} {language_label}'
181
- tracking_headers = {
182
- 'x-goog-api-client': version_header_value,
183
- 'user-agent': version_header_value,
184
- }
185
- return tracking_headers
186
-
187
- @cached_property
188
- def _live_api_client(self) -> Client:
189
- if self._api_backend == 'vertex':
190
- # use beta version for vertex api
191
- api_version = 'v1beta1'
192
- # use default api version for vertex
193
- return Client(
194
- http_options=types.HttpOptions(
195
- headers=self._tracking_headers, api_version=api_version
196
- )
197
- )
198
- else:
199
- # use v1alpha for ml_dev
200
- api_version = 'v1alpha'
201
- return Client(
202
- http_options=types.HttpOptions(
203
- headers=self._tracking_headers, api_version=api_version
204
- )
205
- )
206
-
207
- @contextlib.asynccontextmanager
208
- async def connect(self, llm_request: LlmRequest) -> BaseLlmConnection:
209
- """Connects to the Gemini model and returns an llm connection.
210
-
211
- Args:
212
- llm_request: LlmRequest, the request to send to the Gemini model.
213
-
214
- Yields:
215
- BaseLlmConnection, the connection to the Gemini model.
216
- """
217
-
218
- llm_request.live_connect_config.system_instruction = types.Content(
219
- role='system',
220
- parts=[
221
- types.Part.from_text(text=llm_request.config.system_instruction)
222
- ],
223
- )
224
- llm_request.live_connect_config.tools = llm_request.config.tools
225
- async with self._live_api_client.aio.live.connect(
226
- model=llm_request.model, config=llm_request.live_connect_config
227
- ) as live_session:
228
- yield GeminiLlmConnection(live_session)
229
-
230
-
231
- def _build_function_declaration_log(
232
- func_decl: types.FunctionDeclaration,
233
- ) -> str:
234
- param_str = '{}'
235
- if func_decl.parameters and func_decl.parameters.properties:
236
- param_str = str({
237
- k: v.model_dump(exclude_none=True)
238
- for k, v in func_decl.parameters.properties.items()
239
- })
240
- return_str = 'None'
241
- if func_decl.response:
242
- return_str = str(func_decl.response.model_dump(exclude_none=True))
243
- return f'{func_decl.name}: {param_str} -> {return_str}'
244
-
245
-
246
- def _build_request_log(req: LlmRequest) -> str:
247
- function_decls: list[types.FunctionDeclaration] = cast(
248
- list[types.FunctionDeclaration],
249
- req.config.tools[0].function_declarations if req.config.tools else [],
250
- )
251
- function_logs = (
252
- [
253
- _build_function_declaration_log(func_decl)
254
- for func_decl in function_decls
255
- ]
256
- if function_decls
257
- else []
258
- )
259
- contents_logs = [
260
- content.model_dump_json(
261
- exclude_none=True,
262
- exclude={
263
- 'parts': {
264
- i: _EXCLUDED_PART_FIELD for i in range(len(content.parts))
265
- }
266
- },
267
- )
268
- for content in req.contents
269
- ]
270
-
271
- return f"""
272
- LLM Request:
273
- -----------------------------------------------------------
274
- System Instruction:
275
- {req.config.system_instruction}
276
- -----------------------------------------------------------
277
- Contents:
278
- {_NEW_LINE.join(contents_logs)}
279
- -----------------------------------------------------------
280
- Functions:
281
- {_NEW_LINE.join(function_logs)}
282
- -----------------------------------------------------------
283
- """
284
-
285
-
286
- def _build_response_log(resp: types.GenerateContentResponse) -> str:
287
- function_calls_text = []
288
- if function_calls := resp.function_calls:
289
- for func_call in function_calls:
290
- function_calls_text.append(
291
- f'name: {func_call.name}, args: {func_call.args}'
292
- )
293
- return f"""
294
- LLM Response:
295
- -----------------------------------------------------------
296
- Text:
297
- {resp.text}
298
- -----------------------------------------------------------
299
- Function calls:
300
- {_NEW_LINE.join(function_calls_text)}
301
- -----------------------------------------------------------
302
- Raw response:
303
- {resp.model_dump_json(exclude_none=True)}
304
- -----------------------------------------------------------
305
- """
@@ -1,70 +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 __future__ import annotations
16
-
17
- import logging
18
- from typing import TYPE_CHECKING
19
-
20
- from deprecated import deprecated
21
- from google.genai import types
22
- from typing_extensions import override
23
-
24
- from .base_tool import BaseTool
25
- from .tool_context import ToolContext
26
-
27
- if TYPE_CHECKING:
28
- from ..models import LlmRequest
29
-
30
- logger = logging.getLogger('google_adk.' + __name__)
31
-
32
-
33
- @deprecated(
34
- 'No longer supported. Please use the new BuiltInCodeExecutor instead.'
35
- )
36
- class BuiltInCodeExecutionTool(BaseTool):
37
- """A built-in code execution tool that is automatically invoked by Gemini 2 models.
38
-
39
- This tool operates internally within the model and does not require or perform
40
- local code execution.
41
- """
42
-
43
- def __init__(self):
44
- # Name and description are not used because this is a model built-in tool.
45
- super().__init__(name='code_execution', description='code_execution')
46
-
47
- @override
48
- async def process_llm_request(
49
- self,
50
- *,
51
- tool_context: ToolContext,
52
- llm_request: LlmRequest,
53
- ) -> None:
54
- logger.warning(
55
- 'BuiltInCodeExecutionTool is deprecated and will be removed in 1.1.0.'
56
- ' Please use the new BuiltInCodeExecutor instead.'
57
- )
58
- if llm_request.model and llm_request.model.startswith('gemini-2'):
59
- llm_request.config = llm_request.config or types.GenerateContentConfig()
60
- llm_request.config.tools = llm_request.config.tools or []
61
- llm_request.config.tools.append(
62
- types.Tool(code_execution=types.ToolCodeExecution())
63
- )
64
- else:
65
- raise ValueError(
66
- f'Code execution tool is not supported for model {llm_request.model}'
67
- )
68
-
69
-
70
- built_in_code_execution = BuiltInCodeExecutionTool()