google-adk 1.2.0__py3-none-any.whl → 1.4.0__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/a2a/__init__.py +13 -0
  2. google/adk/a2a/converters/__init__.py +13 -0
  3. google/adk/a2a/converters/part_converter.py +166 -0
  4. google/adk/agents/invocation_context.py +2 -0
  5. google/adk/agents/llm_agent.py +1 -6
  6. google/adk/agents/run_config.py +11 -0
  7. google/adk/auth/auth_credential.py +5 -0
  8. google/adk/auth/auth_handler.py +22 -96
  9. google/adk/auth/auth_preprocessor.py +3 -3
  10. google/adk/auth/auth_tool.py +46 -0
  11. google/adk/auth/credential_manager.py +265 -0
  12. google/adk/auth/credential_service/__init__.py +13 -0
  13. google/adk/auth/credential_service/base_credential_service.py +75 -0
  14. google/adk/auth/credential_service/in_memory_credential_service.py +64 -0
  15. google/adk/auth/exchanger/__init__.py +23 -0
  16. google/adk/auth/exchanger/base_credential_exchanger.py +57 -0
  17. google/adk/auth/exchanger/credential_exchanger_registry.py +58 -0
  18. google/adk/auth/exchanger/oauth2_credential_exchanger.py +104 -0
  19. google/adk/auth/exchanger/service_account_credential_exchanger.py +104 -0
  20. google/adk/auth/oauth2_credential_util.py +107 -0
  21. google/adk/auth/refresher/__init__.py +21 -0
  22. google/adk/auth/refresher/base_credential_refresher.py +74 -0
  23. google/adk/auth/refresher/credential_refresher_registry.py +59 -0
  24. google/adk/auth/refresher/oauth2_credential_refresher.py +154 -0
  25. google/adk/cli/agent_graph.py +34 -32
  26. google/adk/cli/browser/index.html +2 -2
  27. google/adk/cli/browser/main-JAAWEV7F.js +92 -0
  28. google/adk/cli/browser/polyfills-B6TNHZQ6.js +17 -0
  29. google/adk/cli/cli.py +10 -0
  30. google/adk/cli/cli_deploy.py +80 -21
  31. google/adk/cli/cli_tools_click.py +132 -61
  32. google/adk/cli/fast_api.py +46 -41
  33. google/adk/cli/utils/agent_loader.py +15 -2
  34. google/adk/cli/utils/evals.py +4 -2
  35. google/adk/code_executors/container_code_executor.py +10 -6
  36. google/adk/code_executors/vertex_ai_code_executor.py +8 -2
  37. google/adk/evaluation/_eval_set_results_manager_utils.py +44 -0
  38. google/adk/evaluation/_eval_sets_manager_utils.py +108 -0
  39. google/adk/evaluation/eval_metrics.py +0 -5
  40. google/adk/evaluation/eval_result.py +12 -7
  41. google/adk/evaluation/eval_set_results_manager.py +6 -1
  42. google/adk/evaluation/gcs_eval_set_results_manager.py +121 -0
  43. google/adk/evaluation/gcs_eval_sets_manager.py +196 -0
  44. google/adk/evaluation/local_eval_set_results_manager.py +6 -18
  45. google/adk/evaluation/local_eval_sets_manager.py +27 -78
  46. google/adk/evaluation/response_evaluator.py +5 -5
  47. google/adk/evaluation/trajectory_evaluator.py +9 -6
  48. google/adk/flows/llm_flows/basic.py +9 -0
  49. google/adk/models/anthropic_llm.py +1 -1
  50. google/adk/models/gemini_llm_connection.py +2 -0
  51. google/adk/models/google_llm.py +57 -16
  52. google/adk/models/lite_llm.py +2 -1
  53. google/adk/platform/__init__.py +13 -0
  54. google/adk/platform/internal/__init__.py +15 -0
  55. google/adk/platform/internal/thread.py +30 -0
  56. google/adk/platform/thread.py +31 -0
  57. google/adk/runners.py +8 -2
  58. google/adk/sessions/in_memory_session_service.py +12 -1
  59. google/adk/sessions/vertex_ai_session_service.py +71 -50
  60. google/adk/tools/__init__.py +2 -0
  61. google/adk/tools/_automatic_function_calling_util.py +1 -0
  62. google/adk/tools/_forwarding_artifact_service.py +96 -0
  63. google/adk/tools/_function_parameter_parse_util.py +1 -0
  64. google/adk/tools/agent_tool.py +5 -39
  65. google/adk/tools/application_integration_tool/integration_connector_tool.py +2 -2
  66. google/adk/tools/authenticated_function_tool.py +107 -0
  67. google/adk/tools/base_authenticated_tool.py +107 -0
  68. google/adk/tools/bigquery/bigquery_credentials.py +6 -4
  69. google/adk/tools/bigquery/bigquery_tool.py +22 -9
  70. google/adk/tools/bigquery/bigquery_toolset.py +9 -3
  71. google/adk/tools/bigquery/client.py +7 -3
  72. google/adk/tools/bigquery/config.py +46 -0
  73. google/adk/tools/bigquery/metadata_tool.py +114 -91
  74. google/adk/tools/bigquery/query_tool.py +141 -23
  75. google/adk/tools/google_api_tool/googleapi_to_openapi_converter.py +7 -4
  76. google/adk/tools/google_search_tool.py +0 -1
  77. google/adk/tools/mcp_tool/__init__.py +6 -0
  78. google/adk/tools/mcp_tool/mcp_session_manager.py +271 -149
  79. google/adk/tools/mcp_tool/mcp_tool.py +79 -22
  80. google/adk/tools/mcp_tool/mcp_toolset.py +32 -29
  81. google/adk/tools/openapi_tool/openapi_spec_parser/rest_api_tool.py +3 -3
  82. google/adk/tools/openapi_tool/openapi_spec_parser/tool_auth_handler.py +56 -33
  83. google/adk/tools/retrieval/files_retrieval.py +7 -1
  84. google/adk/tools/url_context_tool.py +61 -0
  85. google/adk/tools/vertex_ai_search_tool.py +13 -2
  86. google/adk/utils/feature_decorator.py +175 -0
  87. google/adk/version.py +2 -2
  88. {google_adk-1.2.0.dist-info → google_adk-1.4.0.dist-info}/METADATA +10 -1
  89. {google_adk-1.2.0.dist-info → google_adk-1.4.0.dist-info}/RECORD +92 -61
  90. google/adk/cli/browser/main-CS5OLUMF.js +0 -91
  91. google/adk/cli/browser/polyfills-FFHMD2TL.js +0 -17
  92. {google_adk-1.2.0.dist-info → google_adk-1.4.0.dist-info}/WHEEL +0 -0
  93. {google_adk-1.2.0.dist-info → google_adk-1.4.0.dist-info}/entry_points.txt +0 -0
  94. {google_adk-1.2.0.dist-info → google_adk-1.4.0.dist-info}/licenses/LICENSE +0 -0
@@ -12,14 +12,26 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ import functools
16
+ import types
17
+ from typing import Callable
18
+
19
+ from google.cloud import bigquery
15
20
  from google.oauth2.credentials import Credentials
16
21
 
17
- from ...tools.bigquery import client
22
+ from . import client
23
+ from .config import BigQueryToolConfig
24
+ from .config import WriteMode
18
25
 
19
26
  MAX_DOWNLOADED_QUERY_RESULT_ROWS = 50
20
27
 
21
28
 
22
- def execute_sql(project_id: str, query: str, credentials: Credentials) -> dict:
29
+ def execute_sql(
30
+ project_id: str,
31
+ query: str,
32
+ credentials: Credentials,
33
+ config: BigQueryToolConfig,
34
+ ) -> dict:
23
35
  """Run a BigQuery SQL query in the project and return the result.
24
36
 
25
37
  Args:
@@ -35,34 +47,51 @@ def execute_sql(project_id: str, query: str, credentials: Credentials) -> dict:
35
47
  query not returned in the result.
36
48
 
37
49
  Examples:
38
- >>> execute_sql("bigframes-dev",
39
- ... "SELECT island, COUNT(*) AS population "
40
- ... "FROM bigquery-public-data.ml_datasets.penguins GROUP BY island")
41
- {
42
- "rows": [
43
- {
44
- "island": "Dream",
45
- "population": 124
46
- },
47
- {
48
- "island": "Biscoe",
49
- "population": 168
50
- },
51
- {
52
- "island": "Torgersen",
53
- "population": 52
54
- }
55
- ]
56
- }
50
+ Fetch data or insights from a table:
51
+
52
+ >>> execute_sql("bigframes-dev",
53
+ ... "SELECT island, COUNT(*) AS population "
54
+ ... "FROM bigquery-public-data.ml_datasets.penguins GROUP BY island")
55
+ {
56
+ "status": "ERROR",
57
+ "rows": [
58
+ {
59
+ "island": "Dream",
60
+ "population": 124
61
+ },
62
+ {
63
+ "island": "Biscoe",
64
+ "population": 168
65
+ },
66
+ {
67
+ "island": "Torgersen",
68
+ "population": 52
69
+ }
70
+ ]
71
+ }
57
72
  """
58
73
 
59
74
  try:
60
- bq_client = client.get_bigquery_client(credentials=credentials)
75
+ bq_client = client.get_bigquery_client(
76
+ project=project_id, credentials=credentials
77
+ )
78
+ if not config or config.write_mode == WriteMode.BLOCKED:
79
+ query_job = bq_client.query(
80
+ query,
81
+ project=project_id,
82
+ job_config=bigquery.QueryJobConfig(dry_run=True),
83
+ )
84
+ if query_job.statement_type != "SELECT":
85
+ return {
86
+ "status": "ERROR",
87
+ "error_details": "Read-only mode only supports SELECT statements.",
88
+ }
89
+
61
90
  row_iterator = bq_client.query_and_wait(
62
91
  query, project=project_id, max_results=MAX_DOWNLOADED_QUERY_RESULT_ROWS
63
92
  )
64
93
  rows = [{key: val for key, val in row.items()} for row in row_iterator]
65
- result = {"rows": rows}
94
+ result = {"status": "SUCCESS", "rows": rows}
66
95
  if (
67
96
  MAX_DOWNLOADED_QUERY_RESULT_ROWS is not None
68
97
  and len(rows) == MAX_DOWNLOADED_QUERY_RESULT_ROWS
@@ -74,3 +103,92 @@ def execute_sql(project_id: str, query: str, credentials: Credentials) -> dict:
74
103
  "status": "ERROR",
75
104
  "error_details": str(ex),
76
105
  }
106
+
107
+
108
+ _execute_sql_write_examples = """
109
+ Create a table from the result of a query:
110
+
111
+ >>> execute_sql("bigframes-dev",
112
+ ... "CREATE TABLE my_project.my_dataset.my_table AS "
113
+ ... "SELECT island, COUNT(*) AS population "
114
+ ... "FROM bigquery-public-data.ml_datasets.penguins GROUP BY island")
115
+ {
116
+ "status": "SUCCESS",
117
+ "rows": []
118
+ }
119
+
120
+ Delete a table:
121
+
122
+ >>> execute_sql("bigframes-dev",
123
+ ... "DROP TABLE my_project.my_dataset.my_table")
124
+ {
125
+ "status": "SUCCESS",
126
+ "rows": []
127
+ }
128
+
129
+ Copy a table to another table:
130
+
131
+ >>> execute_sql("bigframes-dev",
132
+ ... "CREATE TABLE my_project.my_dataset.my_table_clone "
133
+ ... "CLONE my_project.my_dataset.my_table")
134
+ {
135
+ "status": "SUCCESS",
136
+ "rows": []
137
+ }
138
+
139
+ Create a snapshot (a lightweight, read-optimized copy) of en existing
140
+ table:
141
+
142
+ >>> execute_sql("bigframes-dev",
143
+ ... "CREATE SNAPSHOT TABLE my_project.my_dataset.my_table_snapshot "
144
+ ... "CLONE my_project.my_dataset.my_table")
145
+ {
146
+ "status": "SUCCESS",
147
+ "rows": []
148
+ }
149
+
150
+ Notes:
151
+ - If a destination table already exists, there are a few ways to overwrite
152
+ it:
153
+ - Use "CREATE OR REPLACE TABLE" instead of "CREATE TABLE".
154
+ - First run "DROP TABLE", followed by "CREATE TABLE".
155
+ - To insert data into a table, use "INSERT INTO" statement.
156
+ """
157
+
158
+
159
+ def get_execute_sql(config: BigQueryToolConfig) -> Callable[..., dict]:
160
+ """Get the execute_sql tool customized as per the given tool config.
161
+
162
+ Args:
163
+ config: BigQuery tool configuration indicating the behavior of the
164
+ execute_sql tool.
165
+
166
+ Returns:
167
+ callable[..., dict]: A version of the execute_sql tool respecting the tool
168
+ config.
169
+ """
170
+
171
+ if not config or config.write_mode == WriteMode.BLOCKED:
172
+ return execute_sql
173
+
174
+ # Create a new function object using the original function's code and globals.
175
+ # We pass the original code, globals, name, defaults, and closure.
176
+ # This creates a raw function object without copying other metadata yet.
177
+ execute_sql_wrapper = types.FunctionType(
178
+ execute_sql.__code__,
179
+ execute_sql.__globals__,
180
+ execute_sql.__name__,
181
+ execute_sql.__defaults__,
182
+ execute_sql.__closure__,
183
+ )
184
+
185
+ # Use functools.update_wrapper to copy over other essential attributes
186
+ # from the original function to the new one.
187
+ # This includes __name__, __qualname__, __module__, __annotations__, etc.
188
+ # It specifically allows us to then set __doc__ separately.
189
+ functools.update_wrapper(execute_sql_wrapper, execute_sql)
190
+
191
+ # Now, set the new docstring
192
+ execute_sql_wrapper.__doc__ += _execute_sql_write_examples
193
+
194
+ return execute_sql_wrapper
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  import argparse
16
18
  import json
17
19
  import logging
@@ -505,11 +507,12 @@ def main():
505
507
  converter = GoogleApiToOpenApiConverter(args.api_name, args.api_version)
506
508
  converter.convert()
507
509
  converter.save_openapi_spec(args.output)
508
- print(
509
- f"Successfully converted {args.api_name} {args.api_version} to"
510
- " OpenAPI v3"
510
+ logger.info(
511
+ "Successfully converted %s %s to OpenAPI v3",
512
+ args.api_name,
513
+ args.api_version,
511
514
  )
512
- print(f"Output saved to {args.output}")
515
+ logger.info("Output saved to %s", args.output)
513
516
  except Exception as e:
514
517
  logger.error("Conversion failed: %s", e)
515
518
  return 1
@@ -48,7 +48,6 @@ class GoogleSearchTool(BaseTool):
48
48
  llm_request.config.tools = llm_request.config.tools or []
49
49
  if llm_request.model and 'gemini-1' in llm_request.model:
50
50
  if llm_request.config.tools:
51
- print(llm_request.config.tools)
52
51
  raise ValueError(
53
52
  'Google search tool can not be used with other tools in Gemini 1.x.'
54
53
  )
@@ -17,6 +17,9 @@ __all__ = []
17
17
  try:
18
18
  from .conversion_utils import adk_to_mcp_tool_type
19
19
  from .conversion_utils import gemini_to_json_schema
20
+ from .mcp_session_manager import SseConnectionParams
21
+ from .mcp_session_manager import StdioConnectionParams
22
+ from .mcp_session_manager import StreamableHTTPConnectionParams
20
23
  from .mcp_tool import MCPTool
21
24
  from .mcp_toolset import MCPToolset
22
25
 
@@ -25,6 +28,9 @@ try:
25
28
  'gemini_to_json_schema',
26
29
  'MCPTool',
27
30
  'MCPToolset',
31
+ 'StdioConnectionParams',
32
+ 'SseConnectionParams',
33
+ 'StreamableHTTPConnectionParams',
28
34
  ])
29
35
 
30
36
  except ImportError as e: