google-adk 0.4.0__py3-none-any.whl → 1.0.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.
- google/adk/agents/active_streaming_tool.py +1 -0
- google/adk/agents/base_agent.py +91 -47
- google/adk/agents/base_agent.py.orig +330 -0
- google/adk/agents/callback_context.py +4 -9
- google/adk/agents/invocation_context.py +1 -0
- google/adk/agents/langgraph_agent.py +1 -0
- google/adk/agents/live_request_queue.py +1 -0
- google/adk/agents/llm_agent.py +172 -35
- google/adk/agents/loop_agent.py +1 -1
- google/adk/agents/parallel_agent.py +7 -0
- google/adk/agents/readonly_context.py +7 -1
- google/adk/agents/run_config.py +5 -1
- google/adk/agents/sequential_agent.py +31 -0
- google/adk/agents/transcription_entry.py +5 -2
- google/adk/artifacts/base_artifact_service.py +5 -10
- google/adk/artifacts/gcs_artifact_service.py +9 -9
- google/adk/artifacts/in_memory_artifact_service.py +6 -6
- google/adk/auth/auth_credential.py +9 -5
- google/adk/auth/auth_preprocessor.py +7 -1
- google/adk/auth/auth_tool.py +3 -4
- google/adk/cli/agent_graph.py +5 -5
- google/adk/cli/browser/index.html +2 -2
- google/adk/cli/browser/{main-HWIBUY2R.js → main-QOEMUXM4.js} +58 -58
- google/adk/cli/cli.py +7 -7
- google/adk/cli/cli_deploy.py +7 -2
- google/adk/cli/cli_eval.py +181 -106
- google/adk/cli/cli_tools_click.py +147 -62
- google/adk/cli/fast_api.py +340 -158
- google/adk/cli/fast_api.py.orig +822 -0
- google/adk/cli/utils/common.py +23 -0
- google/adk/cli/utils/evals.py +83 -1
- google/adk/cli/utils/logs.py +13 -5
- google/adk/code_executors/__init__.py +3 -1
- google/adk/code_executors/built_in_code_executor.py +52 -0
- google/adk/evaluation/__init__.py +1 -1
- google/adk/evaluation/agent_evaluator.py +168 -128
- google/adk/evaluation/eval_case.py +102 -0
- google/adk/evaluation/eval_set.py +37 -0
- google/adk/evaluation/eval_sets_manager.py +42 -0
- google/adk/evaluation/evaluation_constants.py +1 -0
- google/adk/evaluation/evaluation_generator.py +89 -114
- google/adk/evaluation/evaluator.py +56 -0
- google/adk/evaluation/local_eval_sets_manager.py +264 -0
- google/adk/evaluation/response_evaluator.py +107 -3
- google/adk/evaluation/trajectory_evaluator.py +83 -2
- google/adk/events/event.py +7 -1
- google/adk/events/event_actions.py +7 -1
- google/adk/examples/example.py +1 -0
- google/adk/examples/example_util.py +3 -2
- google/adk/flows/__init__.py +0 -1
- google/adk/flows/llm_flows/_code_execution.py +19 -11
- google/adk/flows/llm_flows/audio_transcriber.py +4 -3
- google/adk/flows/llm_flows/base_llm_flow.py +86 -22
- google/adk/flows/llm_flows/basic.py +3 -0
- google/adk/flows/llm_flows/functions.py +10 -9
- google/adk/flows/llm_flows/instructions.py +28 -9
- google/adk/flows/llm_flows/single_flow.py +1 -1
- google/adk/memory/__init__.py +1 -1
- google/adk/memory/_utils.py +23 -0
- google/adk/memory/base_memory_service.py +25 -21
- google/adk/memory/base_memory_service.py.orig +76 -0
- google/adk/memory/in_memory_memory_service.py +59 -27
- google/adk/memory/memory_entry.py +37 -0
- google/adk/memory/vertex_ai_rag_memory_service.py +40 -17
- google/adk/models/anthropic_llm.py +36 -11
- google/adk/models/base_llm.py +45 -4
- google/adk/models/gemini_llm_connection.py +15 -2
- google/adk/models/google_llm.py +9 -44
- google/adk/models/google_llm.py.orig +305 -0
- google/adk/models/lite_llm.py +94 -38
- google/adk/models/llm_request.py +1 -1
- google/adk/models/llm_response.py +15 -3
- google/adk/models/registry.py +1 -1
- google/adk/runners.py +68 -44
- google/adk/sessions/__init__.py +1 -1
- google/adk/sessions/_session_util.py +14 -0
- google/adk/sessions/base_session_service.py +8 -32
- google/adk/sessions/database_session_service.py +58 -61
- google/adk/sessions/in_memory_session_service.py +108 -26
- google/adk/sessions/session.py +4 -0
- google/adk/sessions/vertex_ai_session_service.py +23 -45
- google/adk/telemetry.py +3 -0
- google/adk/tools/__init__.py +4 -7
- google/adk/tools/{built_in_code_execution_tool.py → _built_in_code_execution_tool.py} +11 -0
- google/adk/tools/_memory_entry_utils.py +30 -0
- google/adk/tools/agent_tool.py +16 -13
- google/adk/tools/apihub_tool/apihub_toolset.py +55 -74
- google/adk/tools/application_integration_tool/application_integration_toolset.py +107 -85
- google/adk/tools/application_integration_tool/clients/connections_client.py +29 -25
- google/adk/tools/application_integration_tool/clients/integration_client.py +6 -6
- google/adk/tools/application_integration_tool/integration_connector_tool.py +69 -26
- google/adk/tools/base_toolset.py +58 -0
- google/adk/tools/enterprise_search_tool.py +65 -0
- google/adk/tools/function_parameter_parse_util.py +2 -2
- google/adk/tools/google_api_tool/__init__.py +18 -70
- google/adk/tools/google_api_tool/google_api_tool.py +11 -5
- google/adk/tools/google_api_tool/google_api_toolset.py +126 -0
- google/adk/tools/google_api_tool/google_api_toolsets.py +102 -0
- google/adk/tools/google_api_tool/googleapi_to_openapi_converter.py +40 -42
- google/adk/tools/langchain_tool.py +96 -49
- google/adk/tools/load_artifacts_tool.py +4 -4
- google/adk/tools/load_memory_tool.py +16 -5
- google/adk/tools/mcp_tool/__init__.py +3 -2
- google/adk/tools/mcp_tool/conversion_utils.py +1 -1
- google/adk/tools/mcp_tool/mcp_session_manager.py +167 -16
- google/adk/tools/mcp_tool/mcp_session_manager.py.orig +322 -0
- google/adk/tools/mcp_tool/mcp_tool.py +12 -12
- google/adk/tools/mcp_tool/mcp_toolset.py +155 -195
- google/adk/tools/openapi_tool/common/common.py +2 -5
- google/adk/tools/openapi_tool/openapi_spec_parser/openapi_toolset.py +32 -7
- google/adk/tools/openapi_tool/openapi_spec_parser/operation_parser.py +43 -33
- google/adk/tools/openapi_tool/openapi_spec_parser/tool_auth_handler.py +1 -1
- google/adk/tools/preload_memory_tool.py +27 -18
- google/adk/tools/retrieval/__init__.py +1 -1
- google/adk/tools/retrieval/vertex_ai_rag_retrieval.py +1 -1
- google/adk/tools/tool_context.py +4 -4
- google/adk/tools/toolbox_toolset.py +79 -0
- google/adk/tools/transfer_to_agent_tool.py +0 -1
- google/adk/version.py +1 -1
- {google_adk-0.4.0.dist-info → google_adk-1.0.0.dist-info}/METADATA +7 -5
- google_adk-1.0.0.dist-info/RECORD +195 -0
- google/adk/agents/remote_agent.py +0 -50
- google/adk/tools/google_api_tool/google_api_tool_set.py +0 -110
- google/adk/tools/google_api_tool/google_api_tool_sets.py +0 -112
- google/adk/tools/toolbox_tool.py +0 -46
- google_adk-0.4.0.dist-info/RECORD +0 -179
- {google_adk-0.4.0.dist-info → google_adk-1.0.0.dist-info}/WHEEL +0 -0
- {google_adk-0.4.0.dist-info → google_adk-1.0.0.dist-info}/entry_points.txt +0 -0
- {google_adk-0.4.0.dist-info → google_adk-1.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -312,9 +312,7 @@ class ConnectionsClient:
|
|
312
312
|
"content": {
|
313
313
|
"application/json": {
|
314
314
|
"schema": {
|
315
|
-
"$ref":
|
316
|
-
f"#/components/schemas/{action_display_name}_Request"
|
317
|
-
)
|
315
|
+
"$ref": f"#/components/schemas/{action_display_name}_Request"
|
318
316
|
}
|
319
317
|
}
|
320
318
|
}
|
@@ -325,9 +323,7 @@ class ConnectionsClient:
|
|
325
323
|
"content": {
|
326
324
|
"application/json": {
|
327
325
|
"schema": {
|
328
|
-
"$ref":
|
329
|
-
f"#/components/schemas/{action_display_name}_Response"
|
330
|
-
),
|
326
|
+
"$ref": f"#/components/schemas/{action_display_name}_Response",
|
331
327
|
}
|
332
328
|
}
|
333
329
|
},
|
@@ -346,11 +342,9 @@ class ConnectionsClient:
|
|
346
342
|
return {
|
347
343
|
"post": {
|
348
344
|
"summary": f"List {entity}",
|
349
|
-
"description":
|
350
|
-
f"""Returns the list of {entity} data. If the page token was available in the response, let users know there are more records available. Ask if the user wants to fetch the next page of results. When passing filter use the
|
345
|
+
"description": f"""Returns the list of {entity} data. If the page token was available in the response, let users know there are more records available. Ask if the user wants to fetch the next page of results. When passing filter use the
|
351
346
|
following format: `field_name1='value1' AND field_name2='value2'
|
352
|
-
`. {tool_instructions}"""
|
353
|
-
),
|
347
|
+
`. {tool_instructions}""",
|
354
348
|
"x-operation": "LIST_ENTITIES",
|
355
349
|
"x-entity": f"{entity}",
|
356
350
|
"operationId": f"{tool_name}_list_{entity}",
|
@@ -375,9 +369,7 @@ class ConnectionsClient:
|
|
375
369
|
f"Returns a list of {entity} of json"
|
376
370
|
f" schema: {schema_as_string}"
|
377
371
|
),
|
378
|
-
"$ref":
|
379
|
-
"#/components/schemas/execute-connector_Response"
|
380
|
-
),
|
372
|
+
"$ref": "#/components/schemas/execute-connector_Response",
|
381
373
|
}
|
382
374
|
}
|
383
375
|
},
|
@@ -421,9 +413,7 @@ class ConnectionsClient:
|
|
421
413
|
f"Returns {entity} of json schema:"
|
422
414
|
f" {schema_as_string}"
|
423
415
|
),
|
424
|
-
"$ref":
|
425
|
-
"#/components/schemas/execute-connector_Response"
|
426
|
-
),
|
416
|
+
"$ref": "#/components/schemas/execute-connector_Response",
|
427
417
|
}
|
428
418
|
}
|
429
419
|
},
|
@@ -460,9 +450,7 @@ class ConnectionsClient:
|
|
460
450
|
"content": {
|
461
451
|
"application/json": {
|
462
452
|
"schema": {
|
463
|
-
"$ref":
|
464
|
-
"#/components/schemas/execute-connector_Response"
|
465
|
-
)
|
453
|
+
"$ref": "#/components/schemas/execute-connector_Response"
|
466
454
|
}
|
467
455
|
}
|
468
456
|
},
|
@@ -499,9 +487,7 @@ class ConnectionsClient:
|
|
499
487
|
"content": {
|
500
488
|
"application/json": {
|
501
489
|
"schema": {
|
502
|
-
"$ref":
|
503
|
-
"#/components/schemas/execute-connector_Response"
|
504
|
-
)
|
490
|
+
"$ref": "#/components/schemas/execute-connector_Response"
|
505
491
|
}
|
506
492
|
}
|
507
493
|
},
|
@@ -538,9 +524,7 @@ class ConnectionsClient:
|
|
538
524
|
"content": {
|
539
525
|
"application/json": {
|
540
526
|
"schema": {
|
541
|
-
"$ref":
|
542
|
-
"#/components/schemas/execute-connector_Response"
|
543
|
-
)
|
527
|
+
"$ref": "#/components/schemas/execute-connector_Response"
|
544
528
|
}
|
545
529
|
}
|
546
530
|
},
|
@@ -570,6 +554,9 @@ class ConnectionsClient:
|
|
570
554
|
"serviceName": {"$ref": "#/components/schemas/serviceName"},
|
571
555
|
"host": {"$ref": "#/components/schemas/host"},
|
572
556
|
"entity": {"$ref": "#/components/schemas/entity"},
|
557
|
+
"dynamicAuthConfig": {
|
558
|
+
"$ref": "#/components/schemas/dynamicAuthConfig"
|
559
|
+
},
|
573
560
|
},
|
574
561
|
}
|
575
562
|
|
@@ -596,6 +583,10 @@ class ConnectionsClient:
|
|
596
583
|
"serviceName": {"$ref": "#/components/schemas/serviceName"},
|
597
584
|
"host": {"$ref": "#/components/schemas/host"},
|
598
585
|
"entity": {"$ref": "#/components/schemas/entity"},
|
586
|
+
"dynamicAuthConfig": {
|
587
|
+
"$ref": "#/components/schemas/dynamicAuthConfig"
|
588
|
+
},
|
589
|
+
"filterClause": {"$ref": "#/components/schemas/filterClause"},
|
599
590
|
},
|
600
591
|
}
|
601
592
|
|
@@ -618,6 +609,9 @@ class ConnectionsClient:
|
|
618
609
|
"serviceName": {"$ref": "#/components/schemas/serviceName"},
|
619
610
|
"host": {"$ref": "#/components/schemas/host"},
|
620
611
|
"entity": {"$ref": "#/components/schemas/entity"},
|
612
|
+
"dynamicAuthConfig": {
|
613
|
+
"$ref": "#/components/schemas/dynamicAuthConfig"
|
614
|
+
},
|
621
615
|
},
|
622
616
|
}
|
623
617
|
|
@@ -640,6 +634,10 @@ class ConnectionsClient:
|
|
640
634
|
"serviceName": {"$ref": "#/components/schemas/serviceName"},
|
641
635
|
"host": {"$ref": "#/components/schemas/host"},
|
642
636
|
"entity": {"$ref": "#/components/schemas/entity"},
|
637
|
+
"dynamicAuthConfig": {
|
638
|
+
"$ref": "#/components/schemas/dynamicAuthConfig"
|
639
|
+
},
|
640
|
+
"filterClause": {"$ref": "#/components/schemas/filterClause"},
|
643
641
|
},
|
644
642
|
}
|
645
643
|
|
@@ -663,6 +661,9 @@ class ConnectionsClient:
|
|
663
661
|
"serviceName": {"$ref": "#/components/schemas/serviceName"},
|
664
662
|
"host": {"$ref": "#/components/schemas/host"},
|
665
663
|
"entity": {"$ref": "#/components/schemas/entity"},
|
664
|
+
"dynamicAuthConfig": {
|
665
|
+
"$ref": "#/components/schemas/dynamicAuthConfig"
|
666
|
+
},
|
666
667
|
},
|
667
668
|
}
|
668
669
|
|
@@ -687,6 +688,9 @@ class ConnectionsClient:
|
|
687
688
|
"connectorInputPayload": {
|
688
689
|
"$ref": f"#/components/schemas/connectorInputPayload_{action}"
|
689
690
|
},
|
691
|
+
"dynamicAuthConfig": {
|
692
|
+
"$ref": "#/components/schemas/dynamicAuthConfig"
|
693
|
+
},
|
690
694
|
},
|
691
695
|
}
|
692
696
|
|
@@ -13,7 +13,7 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
import json
|
16
|
-
from typing import Optional
|
16
|
+
from typing import List, Optional
|
17
17
|
from google.adk.tools.application_integration_tool.clients.connections_client import ConnectionsClient
|
18
18
|
import google.auth
|
19
19
|
from google.auth import default as default_service_credential
|
@@ -35,7 +35,7 @@ class IntegrationClient:
|
|
35
35
|
project: str,
|
36
36
|
location: str,
|
37
37
|
integration: Optional[str] = None,
|
38
|
-
|
38
|
+
triggers: Optional[List[str]] = None,
|
39
39
|
connection: Optional[str] = None,
|
40
40
|
entity_operations: Optional[dict[str, list[str]]] = None,
|
41
41
|
actions: Optional[list[str]] = None,
|
@@ -47,7 +47,7 @@ class IntegrationClient:
|
|
47
47
|
project: The Google Cloud project ID.
|
48
48
|
location: The Google Cloud location (e.g., us-central1).
|
49
49
|
integration: The integration name.
|
50
|
-
|
50
|
+
triggers: The list of trigger IDs for the integration.
|
51
51
|
connection: The connection name.
|
52
52
|
entity_operations: A dictionary mapping entity names to a list of
|
53
53
|
operations (e.g., LIST, CREATE, UPDATE, DELETE, GET).
|
@@ -59,7 +59,7 @@ class IntegrationClient:
|
|
59
59
|
self.project = project
|
60
60
|
self.location = location
|
61
61
|
self.integration = integration
|
62
|
-
self.
|
62
|
+
self.triggers = triggers
|
63
63
|
self.connection = connection
|
64
64
|
self.entity_operations = (
|
65
65
|
entity_operations if entity_operations is not None else {}
|
@@ -88,7 +88,7 @@ class IntegrationClient:
|
|
88
88
|
"apiTriggerResources": [
|
89
89
|
{
|
90
90
|
"integrationResource": self.integration,
|
91
|
-
"triggerId":
|
91
|
+
"triggerId": self.triggers,
|
92
92
|
},
|
93
93
|
],
|
94
94
|
"fileFormat": "JSON",
|
@@ -109,7 +109,7 @@ class IntegrationClient:
|
|
109
109
|
raise ValueError(
|
110
110
|
"Invalid request. Please check the provided values of"
|
111
111
|
f" project({self.project}), location({self.location}),"
|
112
|
-
f" integration({self.integration})
|
112
|
+
f" integration({self.integration})."
|
113
113
|
) from e
|
114
114
|
raise ValueError(f"Request error: {e}") from e
|
115
115
|
except Exception as e:
|
@@ -12,21 +12,24 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
|
16
15
|
import logging
|
17
16
|
from typing import Any
|
18
17
|
from typing import Dict
|
19
18
|
from typing import Optional
|
19
|
+
from typing import Union
|
20
20
|
|
21
|
-
from google.adk.tools.openapi_tool.openapi_spec_parser.rest_api_tool import RestApiTool
|
22
|
-
from google.adk.tools.openapi_tool.openapi_spec_parser.rest_api_tool import to_gemini_schema
|
23
21
|
from google.genai.types import FunctionDeclaration
|
24
22
|
from typing_extensions import override
|
25
23
|
|
24
|
+
from ...auth.auth_credential import AuthCredential
|
25
|
+
from ...auth.auth_schemes import AuthScheme
|
26
26
|
from .. import BaseTool
|
27
|
+
from ..openapi_tool.openapi_spec_parser.rest_api_tool import RestApiTool
|
28
|
+
from ..openapi_tool.openapi_spec_parser.rest_api_tool import to_gemini_schema
|
29
|
+
from ..openapi_tool.openapi_spec_parser.tool_auth_handler import ToolAuthHandler
|
27
30
|
from ..tool_context import ToolContext
|
28
31
|
|
29
|
-
logger = logging.getLogger(__name__)
|
32
|
+
logger = logging.getLogger('google_adk.' + __name__)
|
30
33
|
|
31
34
|
|
32
35
|
class IntegrationConnectorTool(BaseTool):
|
@@ -56,6 +59,7 @@ class IntegrationConnectorTool(BaseTool):
|
|
56
59
|
'entity',
|
57
60
|
'operation',
|
58
61
|
'action',
|
62
|
+
'dynamic_auth_config',
|
59
63
|
]
|
60
64
|
|
61
65
|
OPTIONAL_FIELDS = [
|
@@ -75,6 +79,8 @@ class IntegrationConnectorTool(BaseTool):
|
|
75
79
|
operation: str,
|
76
80
|
action: str,
|
77
81
|
rest_api_tool: RestApiTool,
|
82
|
+
auth_scheme: Optional[Union[AuthScheme, str]] = None,
|
83
|
+
auth_credential: Optional[Union[AuthCredential, str]] = None,
|
78
84
|
):
|
79
85
|
"""Initializes the ApplicationIntegrationTool.
|
80
86
|
|
@@ -101,18 +107,20 @@ class IntegrationConnectorTool(BaseTool):
|
|
101
107
|
name=name,
|
102
108
|
description=description,
|
103
109
|
)
|
104
|
-
self.
|
105
|
-
self.
|
106
|
-
self.
|
107
|
-
self.
|
108
|
-
self.
|
109
|
-
self.
|
110
|
-
self.
|
110
|
+
self._connection_name = connection_name
|
111
|
+
self._connection_host = connection_host
|
112
|
+
self._connection_service_name = connection_service_name
|
113
|
+
self._entity = entity
|
114
|
+
self._operation = operation
|
115
|
+
self._action = action
|
116
|
+
self._rest_api_tool = rest_api_tool
|
117
|
+
self._auth_scheme = auth_scheme
|
118
|
+
self._auth_credential = auth_credential
|
111
119
|
|
112
120
|
@override
|
113
121
|
def _get_declaration(self) -> FunctionDeclaration:
|
114
122
|
"""Returns the function declaration in the Gemini Schema format."""
|
115
|
-
schema_dict = self.
|
123
|
+
schema_dict = self._rest_api_tool._operation_parser.get_json_schema()
|
116
124
|
for field in self.EXCLUDE_FIELDS:
|
117
125
|
if field in schema_dict['properties']:
|
118
126
|
del schema_dict['properties'][field]
|
@@ -126,34 +134,69 @@ class IntegrationConnectorTool(BaseTool):
|
|
126
134
|
)
|
127
135
|
return function_decl
|
128
136
|
|
137
|
+
def _prepare_dynamic_euc(self, auth_credential: AuthCredential) -> str:
|
138
|
+
if (
|
139
|
+
auth_credential
|
140
|
+
and auth_credential.http
|
141
|
+
and auth_credential.http.credentials
|
142
|
+
and auth_credential.http.credentials.token
|
143
|
+
):
|
144
|
+
return auth_credential.http.credentials.token
|
145
|
+
return None
|
146
|
+
|
129
147
|
@override
|
130
148
|
async def run_async(
|
131
149
|
self, *, args: dict[str, Any], tool_context: Optional[ToolContext]
|
132
150
|
) -> Dict[str, Any]:
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
151
|
+
|
152
|
+
tool_auth_handler = ToolAuthHandler.from_tool_context(
|
153
|
+
tool_context, self._auth_scheme, self._auth_credential
|
154
|
+
)
|
155
|
+
auth_result = tool_auth_handler.prepare_auth_credentials()
|
156
|
+
|
157
|
+
if auth_result.state == 'pending':
|
158
|
+
return {
|
159
|
+
'pending': True,
|
160
|
+
'message': 'Needs your authorization to access your data.',
|
161
|
+
}
|
162
|
+
|
163
|
+
# Attach parameters from auth into main parameters list
|
164
|
+
if auth_result.auth_credential:
|
165
|
+
# Attach parameters from auth into main parameters list
|
166
|
+
auth_credential_token = self._prepare_dynamic_euc(
|
167
|
+
auth_result.auth_credential
|
168
|
+
)
|
169
|
+
if auth_credential_token:
|
170
|
+
args['dynamic_auth_config'] = {
|
171
|
+
'oauth2_auth_code_flow.access_token': auth_credential_token
|
172
|
+
}
|
173
|
+
else:
|
174
|
+
args['dynamic_auth_config'] = {'oauth2_auth_code_flow.access_token': {}}
|
175
|
+
|
176
|
+
args['connection_name'] = self._connection_name
|
177
|
+
args['service_name'] = self._connection_service_name
|
178
|
+
args['host'] = self._connection_host
|
179
|
+
args['entity'] = self._entity
|
180
|
+
args['operation'] = self._operation
|
181
|
+
args['action'] = self._action
|
139
182
|
logger.info('Running tool: %s with args: %s', self.name, args)
|
140
|
-
return self.
|
183
|
+
return self._rest_api_tool.call(args=args, tool_context=tool_context)
|
141
184
|
|
142
185
|
def __str__(self):
|
143
186
|
return (
|
144
187
|
f'ApplicationIntegrationTool(name="{self.name}",'
|
145
188
|
f' description="{self.description}",'
|
146
|
-
f' connection_name="{self.
|
147
|
-
f' operation="{self.
|
189
|
+
f' connection_name="{self._connection_name}", entity="{self._entity}",'
|
190
|
+
f' operation="{self._operation}", action="{self._action}")'
|
148
191
|
)
|
149
192
|
|
150
193
|
def __repr__(self):
|
151
194
|
return (
|
152
195
|
f'ApplicationIntegrationTool(name="{self.name}",'
|
153
196
|
f' description="{self.description}",'
|
154
|
-
f' connection_name="{self.
|
155
|
-
f' connection_host="{self.
|
156
|
-
f' connection_service_name="{self.
|
157
|
-
f' entity="{self.
|
158
|
-
f' action="{self.
|
197
|
+
f' connection_name="{self._connection_name}",'
|
198
|
+
f' connection_host="{self._connection_host}",'
|
199
|
+
f' connection_service_name="{self._connection_service_name}",'
|
200
|
+
f' entity="{self._entity}", operation="{self._operation}",'
|
201
|
+
f' action="{self._action}", rest_api_tool={repr(self._rest_api_tool)})'
|
159
202
|
)
|
@@ -0,0 +1,58 @@
|
|
1
|
+
from abc import ABC
|
2
|
+
from abc import abstractmethod
|
3
|
+
from typing import Optional, runtime_checkable
|
4
|
+
from typing import Protocol
|
5
|
+
|
6
|
+
from ..agents.readonly_context import ReadonlyContext
|
7
|
+
from .base_tool import BaseTool
|
8
|
+
|
9
|
+
|
10
|
+
@runtime_checkable
|
11
|
+
class ToolPredicate(Protocol):
|
12
|
+
"""Base class for a predicate that defines the interface to decide whether a
|
13
|
+
|
14
|
+
tool should be exposed to LLM. Toolset implementer could consider whether to
|
15
|
+
accept such instance in the toolset's constructor and apply the predicate in
|
16
|
+
get_tools method.
|
17
|
+
"""
|
18
|
+
|
19
|
+
def __call__(
|
20
|
+
self, tool: BaseTool, readonly_context: Optional[ReadonlyContext] = None
|
21
|
+
) -> bool:
|
22
|
+
"""Decide whether the passed-in tool should be exposed to LLM based on the
|
23
|
+
|
24
|
+
current context. True if the tool is usable by the LLM.
|
25
|
+
|
26
|
+
It's used to filter tools in the toolset.
|
27
|
+
"""
|
28
|
+
|
29
|
+
|
30
|
+
class BaseToolset(ABC):
|
31
|
+
"""Base class for toolset.
|
32
|
+
|
33
|
+
A toolset is a collection of tools that can be used by an agent.
|
34
|
+
"""
|
35
|
+
|
36
|
+
@abstractmethod
|
37
|
+
async def get_tools(
|
38
|
+
self, readonly_context: Optional[ReadonlyContext] = None
|
39
|
+
) -> list[BaseTool]:
|
40
|
+
"""Return all tools in the toolset based on the provided context.
|
41
|
+
|
42
|
+
Args:
|
43
|
+
readony_context (ReadonlyContext, optional): Context used to filter tools
|
44
|
+
available to the agent. If None, all tools in the toolset are returned.
|
45
|
+
|
46
|
+
Returns:
|
47
|
+
list[BaseTool]: A list of tools available under the specified context.
|
48
|
+
"""
|
49
|
+
|
50
|
+
@abstractmethod
|
51
|
+
async def close(self) -> None:
|
52
|
+
"""Performs cleanup and releases resources held by the toolset.
|
53
|
+
|
54
|
+
NOTE: This method is invoked, for example, at the end of an agent server's
|
55
|
+
lifecycle or when the toolset is no longer needed. Implementations
|
56
|
+
should ensure that any open connections, files, or other managed
|
57
|
+
resources are properly released to prevent leaks.
|
58
|
+
"""
|
@@ -0,0 +1,65 @@
|
|
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
|
+
from typing import TYPE_CHECKING
|
18
|
+
|
19
|
+
from google.genai import types
|
20
|
+
from typing_extensions import override
|
21
|
+
|
22
|
+
from .base_tool import BaseTool
|
23
|
+
from .tool_context import ToolContext
|
24
|
+
|
25
|
+
if TYPE_CHECKING:
|
26
|
+
from ..models import LlmRequest
|
27
|
+
|
28
|
+
|
29
|
+
class EnterpriseWebSearchTool(BaseTool):
|
30
|
+
"""A Gemini 2+ built-in tool using web grounding for Enterprise compliance.
|
31
|
+
|
32
|
+
See the documentation for more details:
|
33
|
+
https://cloud.google.com/vertex-ai/generative-ai/docs/grounding/web-grounding-enterprise.
|
34
|
+
"""
|
35
|
+
|
36
|
+
def __init__(self):
|
37
|
+
"""Initializes the Vertex AI Search tool."""
|
38
|
+
# Name and description are not used because this is a model built-in tool.
|
39
|
+
super().__init__(
|
40
|
+
name='enterprise_web_search', description='enterprise_web_search'
|
41
|
+
)
|
42
|
+
|
43
|
+
@override
|
44
|
+
async def process_llm_request(
|
45
|
+
self,
|
46
|
+
*,
|
47
|
+
tool_context: ToolContext,
|
48
|
+
llm_request: LlmRequest,
|
49
|
+
) -> None:
|
50
|
+
if llm_request.model and llm_request.model.startswith('gemini-'):
|
51
|
+
if llm_request.model.startswith('gemini-1') and llm_request.config.tools:
|
52
|
+
raise ValueError(
|
53
|
+
'Enterprise web search tool can not be used with other tools in'
|
54
|
+
' Gemini 1.x.'
|
55
|
+
)
|
56
|
+
llm_request.config = llm_request.config or types.GenerateContentConfig()
|
57
|
+
llm_request.config.tools = llm_request.config.tools or []
|
58
|
+
llm_request.config.tools.append(
|
59
|
+
types.Tool(enterprise_web_search=types.EnterpriseWebSearch())
|
60
|
+
)
|
61
|
+
else:
|
62
|
+
raise ValueError(
|
63
|
+
'Enterprise web search tool is not supported for model'
|
64
|
+
f' {llm_request.model}'
|
65
|
+
)
|
@@ -35,7 +35,7 @@ _py_builtin_type_to_schema_type = {
|
|
35
35
|
dict: types.Type.OBJECT,
|
36
36
|
}
|
37
37
|
|
38
|
-
logger = logging.getLogger(__name__)
|
38
|
+
logger = logging.getLogger('google_adk.' + __name__)
|
39
39
|
|
40
40
|
|
41
41
|
def _is_builtin_primitive_or_compound(
|
@@ -292,7 +292,7 @@ def _parse_schema_from_parameter(
|
|
292
292
|
raise ValueError(
|
293
293
|
f'Failed to parse the parameter {param} of function {func_name} for'
|
294
294
|
' automatic function calling. Automatic function calling works best with'
|
295
|
-
' simpler function signature schema,consider manually
|
295
|
+
' simpler function signature schema, consider manually parsing your'
|
296
296
|
f' function declaration for function {func_name}.'
|
297
297
|
)
|
298
298
|
|
@@ -12,76 +12,24 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
__all__ = [
|
15
|
-
'
|
16
|
-
'
|
17
|
-
'
|
18
|
-
'
|
19
|
-
'
|
20
|
-
'
|
21
|
-
'
|
15
|
+
'BigQueryToolset',
|
16
|
+
'CalendarToolset',
|
17
|
+
'GmailToolset',
|
18
|
+
'YoutubeToolset',
|
19
|
+
'SlidesToolset',
|
20
|
+
'SheetsToolset',
|
21
|
+
'DocsToolset',
|
22
|
+
'GoogleApiToolset',
|
23
|
+
'GoogleApiTool',
|
22
24
|
]
|
23
25
|
|
24
|
-
# Nothing is imported here automatically
|
25
|
-
# Each tool set will only be imported when accessed
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
def __getattr__(name):
|
37
|
-
global _bigquery_tool_set, _calendar_tool_set, _gmail_tool_set, _youtube_tool_set, _slides_tool_set, _sheets_tool_set, _docs_tool_set
|
38
|
-
|
39
|
-
match name:
|
40
|
-
case 'bigquery_tool_set':
|
41
|
-
if _bigquery_tool_set is None:
|
42
|
-
from .google_api_tool_sets import bigquery_tool_set as bigquery
|
43
|
-
|
44
|
-
_bigquery_tool_set = bigquery
|
45
|
-
return _bigquery_tool_set
|
46
|
-
|
47
|
-
case 'calendar_tool_set':
|
48
|
-
if _calendar_tool_set is None:
|
49
|
-
from .google_api_tool_sets import calendar_tool_set as calendar
|
50
|
-
|
51
|
-
_calendar_tool_set = calendar
|
52
|
-
return _calendar_tool_set
|
53
|
-
|
54
|
-
case 'gmail_tool_set':
|
55
|
-
if _gmail_tool_set is None:
|
56
|
-
from .google_api_tool_sets import gmail_tool_set as gmail
|
57
|
-
|
58
|
-
_gmail_tool_set = gmail
|
59
|
-
return _gmail_tool_set
|
60
|
-
|
61
|
-
case 'youtube_tool_set':
|
62
|
-
if _youtube_tool_set is None:
|
63
|
-
from .google_api_tool_sets import youtube_tool_set as youtube
|
64
|
-
|
65
|
-
_youtube_tool_set = youtube
|
66
|
-
return _youtube_tool_set
|
67
|
-
|
68
|
-
case 'slides_tool_set':
|
69
|
-
if _slides_tool_set is None:
|
70
|
-
from .google_api_tool_sets import slides_tool_set as slides
|
71
|
-
|
72
|
-
_slides_tool_set = slides
|
73
|
-
return _slides_tool_set
|
74
|
-
|
75
|
-
case 'sheets_tool_set':
|
76
|
-
if _sheets_tool_set is None:
|
77
|
-
from .google_api_tool_sets import sheets_tool_set as sheets
|
78
|
-
|
79
|
-
_sheets_tool_set = sheets
|
80
|
-
return _sheets_tool_set
|
81
|
-
|
82
|
-
case 'docs_tool_set':
|
83
|
-
if _docs_tool_set is None:
|
84
|
-
from .google_api_tool_sets import docs_tool_set as docs
|
85
|
-
|
86
|
-
_docs_tool_set = docs
|
87
|
-
return _docs_tool_set
|
27
|
+
from .google_api_tool import GoogleApiTool
|
28
|
+
from .google_api_toolset import GoogleApiToolset
|
29
|
+
from .google_api_toolsets import BigQueryToolset
|
30
|
+
from .google_api_toolsets import CalendarToolset
|
31
|
+
from .google_api_toolsets import DocsToolset
|
32
|
+
from .google_api_toolsets import GmailToolset
|
33
|
+
from .google_api_toolsets import SheetsToolset
|
34
|
+
from .google_api_toolsets import SlidesToolset
|
35
|
+
from .google_api_toolsets import YoutubeToolset
|
@@ -29,28 +29,34 @@ from ..tool_context import ToolContext
|
|
29
29
|
|
30
30
|
class GoogleApiTool(BaseTool):
|
31
31
|
|
32
|
-
def __init__(
|
32
|
+
def __init__(
|
33
|
+
self,
|
34
|
+
rest_api_tool: RestApiTool,
|
35
|
+
client_id: Optional[str] = None,
|
36
|
+
client_secret: Optional[str] = None,
|
37
|
+
):
|
33
38
|
super().__init__(
|
34
39
|
name=rest_api_tool.name,
|
35
40
|
description=rest_api_tool.description,
|
36
41
|
is_long_running=rest_api_tool.is_long_running,
|
37
42
|
)
|
38
|
-
self.
|
43
|
+
self._rest_api_tool = rest_api_tool
|
44
|
+
self.configure_auth(client_id, client_secret)
|
39
45
|
|
40
46
|
@override
|
41
47
|
def _get_declaration(self) -> FunctionDeclaration:
|
42
|
-
return self.
|
48
|
+
return self._rest_api_tool._get_declaration()
|
43
49
|
|
44
50
|
@override
|
45
51
|
async def run_async(
|
46
52
|
self, *, args: dict[str, Any], tool_context: Optional[ToolContext]
|
47
53
|
) -> Dict[str, Any]:
|
48
|
-
return await self.
|
54
|
+
return await self._rest_api_tool.run_async(
|
49
55
|
args=args, tool_context=tool_context
|
50
56
|
)
|
51
57
|
|
52
58
|
def configure_auth(self, client_id: str, client_secret: str):
|
53
|
-
self.
|
59
|
+
self._rest_api_tool.auth_credential = AuthCredential(
|
54
60
|
auth_type=AuthCredentialTypes.OPEN_ID_CONNECT,
|
55
61
|
oauth2=OAuth2Auth(
|
56
62
|
client_id=client_id,
|