google-adk 0.5.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/base_agent.py +76 -30
- google/adk/agents/base_agent.py.orig +330 -0
- google/adk/agents/callback_context.py +0 -5
- google/adk/agents/llm_agent.py +122 -30
- 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 +1 -1
- google/adk/agents/sequential_agent.py +31 -0
- google/adk/agents/transcription_entry.py +4 -2
- google/adk/artifacts/gcs_artifact_service.py +1 -1
- google/adk/artifacts/in_memory_artifact_service.py +1 -1
- google/adk/auth/auth_credential.py +6 -1
- 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-ULN5R5I5.js → main-QOEMUXM4.js} +44 -45
- google/adk/cli/cli.py +7 -7
- google/adk/cli/cli_deploy.py +7 -2
- google/adk/cli/cli_eval.py +172 -99
- google/adk/cli/cli_tools_click.py +147 -64
- google/adk/cli/fast_api.py +330 -148
- google/adk/cli/fast_api.py.orig +174 -80
- 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_generator.py +88 -113
- google/adk/evaluation/evaluator.py +56 -0
- google/adk/evaluation/local_eval_sets_manager.py +264 -0
- google/adk/evaluation/response_evaluator.py +106 -2
- google/adk/evaluation/trajectory_evaluator.py +83 -2
- google/adk/events/event.py +6 -1
- google/adk/events/event_actions.py +6 -1
- google/adk/examples/example_util.py +3 -2
- google/adk/flows/llm_flows/_code_execution.py +9 -1
- google/adk/flows/llm_flows/audio_transcriber.py +4 -3
- google/adk/flows/llm_flows/base_llm_flow.py +54 -15
- google/adk/flows/llm_flows/functions.py +9 -8
- google/adk/flows/llm_flows/instructions.py +13 -5
- 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 +23 -21
- google/adk/memory/base_memory_service.py.orig +76 -0
- google/adk/memory/in_memory_memory_service.py +57 -25
- google/adk/memory/memory_entry.py +37 -0
- google/adk/memory/vertex_ai_rag_memory_service.py +38 -15
- google/adk/models/anthropic_llm.py +16 -9
- google/adk/models/gemini_llm_connection.py +11 -11
- google/adk/models/google_llm.py +9 -2
- google/adk/models/google_llm.py.orig +305 -0
- google/adk/models/lite_llm.py +77 -21
- google/adk/models/llm_response.py +14 -2
- google/adk/models/registry.py +1 -1
- google/adk/runners.py +65 -41
- google/adk/sessions/__init__.py +1 -1
- google/adk/sessions/base_session_service.py +6 -33
- google/adk/sessions/database_session_service.py +58 -65
- google/adk/sessions/in_memory_session_service.py +106 -24
- google/adk/sessions/session.py +3 -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 +9 -9
- 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 +20 -0
- 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_memory_tool.py +14 -5
- google/adk/tools/mcp_tool/__init__.py +3 -2
- google/adk/tools/mcp_tool/mcp_session_manager.py +153 -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/openapi_spec_parser/openapi_toolset.py +32 -7
- google/adk/tools/openapi_tool/openapi_spec_parser/operation_parser.py +31 -31
- 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/toolbox_toolset.py +79 -0
- google/adk/tools/transfer_to_agent_tool.py +0 -1
- google/adk/version.py +1 -1
- {google_adk-0.5.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.5.0.dist-info/RECORD +0 -180
- {google_adk-0.5.0.dist-info → google_adk-1.0.0.dist-info}/WHEEL +0 -0
- {google_adk-0.5.0.dist-info → google_adk-1.0.0.dist-info}/entry_points.txt +0 -0
- {google_adk-0.5.0.dist-info → google_adk-1.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -13,19 +13,25 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
|
16
|
-
from typing import
|
16
|
+
from typing import List
|
17
|
+
from typing import Optional
|
18
|
+
from typing import Union
|
17
19
|
|
20
|
+
from typing_extensions import override
|
18
21
|
import yaml
|
19
22
|
|
23
|
+
from ...agents.readonly_context import ReadonlyContext
|
20
24
|
from ...auth.auth_credential import AuthCredential
|
21
25
|
from ...auth.auth_schemes import AuthScheme
|
26
|
+
from ..base_toolset import BaseToolset
|
27
|
+
from ..base_toolset import ToolPredicate
|
22
28
|
from ..openapi_tool.common.common import to_snake_case
|
23
29
|
from ..openapi_tool.openapi_spec_parser.openapi_toolset import OpenAPIToolset
|
24
30
|
from ..openapi_tool.openapi_spec_parser.rest_api_tool import RestApiTool
|
25
31
|
from .clients.apihub_client import APIHubClient
|
26
32
|
|
27
33
|
|
28
|
-
class APIHubToolset:
|
34
|
+
class APIHubToolset(BaseToolset):
|
29
35
|
"""APIHubTool generates tools from a given API Hub resource.
|
30
36
|
|
31
37
|
Examples:
|
@@ -34,16 +40,13 @@ class APIHubToolset:
|
|
34
40
|
apihub_toolset = APIHubToolset(
|
35
41
|
apihub_resource_name="projects/test-project/locations/us-central1/apis/test-api",
|
36
42
|
service_account_json="...",
|
43
|
+
tool_filter=lambda tool, ctx=None: tool.name in ('my_tool',
|
44
|
+
'my_other_tool')
|
37
45
|
)
|
38
46
|
|
39
47
|
# Get all available tools
|
40
|
-
agent = LlmAgent(tools=apihub_toolset
|
48
|
+
agent = LlmAgent(tools=apihub_toolset)
|
41
49
|
|
42
|
-
# Get a specific tool
|
43
|
-
agent = LlmAgent(tools=[
|
44
|
-
...
|
45
|
-
apihub_toolset.get_tool('my_tool'),
|
46
|
-
])
|
47
50
|
```
|
48
51
|
|
49
52
|
**apihub_resource_name** is the resource name from API Hub. It must include
|
@@ -70,6 +73,7 @@ class APIHubToolset:
|
|
70
73
|
auth_credential: Optional[AuthCredential] = None,
|
71
74
|
# Optionally, you can provide a custom API Hub client
|
72
75
|
apihub_client: Optional[APIHubClient] = None,
|
76
|
+
tool_filter: Optional[Union[ToolPredicate, List[str]]] = None,
|
73
77
|
):
|
74
78
|
"""Initializes the APIHubTool with the given parameters.
|
75
79
|
|
@@ -81,12 +85,17 @@ class APIHubToolset:
|
|
81
85
|
)
|
82
86
|
|
83
87
|
# Get all available tools
|
84
|
-
agent = LlmAgent(tools=apihub_toolset
|
88
|
+
agent = LlmAgent(tools=[apihub_toolset])
|
85
89
|
|
90
|
+
apihub_toolset = APIHubToolset(
|
91
|
+
apihub_resource_name="projects/test-project/locations/us-central1/apis/test-api",
|
92
|
+
service_account_json="...",
|
93
|
+
tool_filter = ['my_tool']
|
94
|
+
)
|
86
95
|
# Get a specific tool
|
87
96
|
agent = LlmAgent(tools=[
|
88
|
-
|
89
|
-
apihub_toolset
|
97
|
+
...,
|
98
|
+
apihub_toolset,
|
90
99
|
])
|
91
100
|
```
|
92
101
|
|
@@ -118,82 +127,49 @@ class APIHubToolset:
|
|
118
127
|
lazy_load_spec: If True, the spec will be loaded lazily when needed.
|
119
128
|
Otherwise, the spec will be loaded immediately and the tools will be
|
120
129
|
generated during initialization.
|
130
|
+
tool_filter: The filter used to filter the tools in the toolset. It can
|
131
|
+
be either a tool predicate or a list of tool names of the tools to
|
132
|
+
expose.
|
121
133
|
"""
|
122
134
|
self.name = name
|
123
135
|
self.description = description
|
124
|
-
self.
|
125
|
-
self.
|
126
|
-
self.
|
136
|
+
self._apihub_resource_name = apihub_resource_name
|
137
|
+
self._lazy_load_spec = lazy_load_spec
|
138
|
+
self._apihub_client = apihub_client or APIHubClient(
|
127
139
|
access_token=access_token,
|
128
140
|
service_account_json=service_account_json,
|
129
141
|
)
|
130
142
|
|
131
|
-
self.
|
132
|
-
self.
|
133
|
-
self.
|
134
|
-
|
135
|
-
if not self.lazy_load_spec:
|
136
|
-
self._prepare_tools()
|
137
|
-
|
138
|
-
def get_tool(self, name: str) -> Optional[RestApiTool]:
|
139
|
-
"""Retrieves a specific tool by its name.
|
140
|
-
|
141
|
-
Example:
|
142
|
-
```
|
143
|
-
apihub_tool = apihub_toolset.get_tool('my_tool')
|
144
|
-
```
|
145
|
-
|
146
|
-
Args:
|
147
|
-
name: The name of the tool to retrieve.
|
148
|
-
|
149
|
-
Returns:
|
150
|
-
The tool with the given name, or None if no such tool exists.
|
151
|
-
"""
|
152
|
-
if not self._are_tools_ready():
|
153
|
-
self._prepare_tools()
|
143
|
+
self._openapi_toolset = None
|
144
|
+
self._auth_scheme = auth_scheme
|
145
|
+
self._auth_credential = auth_credential
|
146
|
+
self.tool_filter = tool_filter
|
154
147
|
|
155
|
-
|
148
|
+
if not self._lazy_load_spec:
|
149
|
+
self._prepare_toolset()
|
156
150
|
|
157
|
-
|
151
|
+
@override
|
152
|
+
async def get_tools(
|
153
|
+
self, readonly_context: Optional[ReadonlyContext] = None
|
154
|
+
) -> List[RestApiTool]:
|
158
155
|
"""Retrieves all available tools.
|
159
156
|
|
160
157
|
Returns:
|
161
158
|
A list of all available RestApiTool objects.
|
162
159
|
"""
|
163
|
-
if not self.
|
164
|
-
self.
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
def _are_tools_ready(self) -> bool:
|
169
|
-
return not self.lazy_load_spec or self.generated_tools
|
170
|
-
|
171
|
-
def _prepare_tools(self) -> str:
|
172
|
-
"""Fetches the spec from API Hub and generates the tools.
|
160
|
+
if not self._openapi_toolset:
|
161
|
+
self._prepare_toolset()
|
162
|
+
if not self._openapi_toolset:
|
163
|
+
return []
|
164
|
+
return await self._openapi_toolset.get_tools(readonly_context)
|
173
165
|
|
174
|
-
|
175
|
-
|
176
|
-
"""
|
166
|
+
def _prepare_toolset(self) -> None:
|
167
|
+
"""Fetches the spec from API Hub and generates the toolset."""
|
177
168
|
# For each API, get the first version and the first spec of that version.
|
178
|
-
|
179
|
-
self.generated_tools: Dict[str, RestApiTool] = {}
|
180
|
-
|
181
|
-
tools = self._parse_spec_to_tools(spec)
|
182
|
-
for tool in tools:
|
183
|
-
self.generated_tools[tool.name] = tool
|
184
|
-
|
185
|
-
def _parse_spec_to_tools(self, spec_str: str) -> List[RestApiTool]:
|
186
|
-
"""Parses the spec string to a list of RestApiTool.
|
187
|
-
|
188
|
-
Args:
|
189
|
-
spec_str: The spec string to parse.
|
190
|
-
|
191
|
-
Returns:
|
192
|
-
A list of RestApiTool objects.
|
193
|
-
"""
|
169
|
+
spec_str = self._apihub_client.get_spec_content(self._apihub_resource_name)
|
194
170
|
spec_dict = yaml.safe_load(spec_str)
|
195
171
|
if not spec_dict:
|
196
|
-
return
|
172
|
+
return
|
197
173
|
|
198
174
|
self.name = self.name or to_snake_case(
|
199
175
|
spec_dict.get('info', {}).get('title', 'unnamed')
|
@@ -201,9 +177,14 @@ class APIHubToolset:
|
|
201
177
|
self.description = self.description or spec_dict.get('info', {}).get(
|
202
178
|
'description', ''
|
203
179
|
)
|
204
|
-
|
180
|
+
self._openapi_toolset = OpenAPIToolset(
|
205
181
|
spec_dict=spec_dict,
|
206
|
-
auth_credential=self.
|
207
|
-
auth_scheme=self.
|
208
|
-
|
209
|
-
|
182
|
+
auth_credential=self._auth_credential,
|
183
|
+
auth_scheme=self._auth_scheme,
|
184
|
+
tool_filter=self.tool_filter,
|
185
|
+
)
|
186
|
+
|
187
|
+
@override
|
188
|
+
async def close(self):
|
189
|
+
if self._openapi_toolset:
|
190
|
+
await self._openapi_toolset.close()
|
@@ -12,14 +12,22 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
|
15
|
+
import logging
|
16
|
+
from typing import List
|
17
|
+
from typing import Optional
|
18
|
+
from typing import Union
|
16
19
|
|
17
20
|
from fastapi.openapi.models import HTTPBearer
|
21
|
+
from typing_extensions import override
|
18
22
|
|
23
|
+
from ...agents.readonly_context import ReadonlyContext
|
19
24
|
from ...auth.auth_credential import AuthCredential
|
20
25
|
from ...auth.auth_credential import AuthCredentialTypes
|
21
26
|
from ...auth.auth_credential import ServiceAccount
|
22
27
|
from ...auth.auth_credential import ServiceAccountCredential
|
28
|
+
from ...auth.auth_schemes import AuthScheme
|
29
|
+
from ..base_toolset import BaseToolset
|
30
|
+
from ..base_toolset import ToolPredicate
|
23
31
|
from ..openapi_tool.auth.auth_helpers import service_account_scheme_credential
|
24
32
|
from ..openapi_tool.openapi_spec_parser.openapi_spec_parser import OpenApiSpecParser
|
25
33
|
from ..openapi_tool.openapi_spec_parser.openapi_toolset import OpenAPIToolset
|
@@ -28,9 +36,11 @@ from .clients.connections_client import ConnectionsClient
|
|
28
36
|
from .clients.integration_client import IntegrationClient
|
29
37
|
from .integration_connector_tool import IntegrationConnectorTool
|
30
38
|
|
39
|
+
logger = logging.getLogger("google_adk." + __name__)
|
40
|
+
|
31
41
|
|
32
42
|
# TODO(cheliu): Apply a common toolset interface
|
33
|
-
class ApplicationIntegrationToolset:
|
43
|
+
class ApplicationIntegrationToolset(BaseToolset):
|
34
44
|
"""ApplicationIntegrationToolset generates tools from a given Application
|
35
45
|
|
36
46
|
Integration or Integration Connector resource.
|
@@ -42,7 +52,7 @@ class ApplicationIntegrationToolset:
|
|
42
52
|
project="test-project",
|
43
53
|
location="us-central1"
|
44
54
|
integration="test-integration",
|
45
|
-
|
55
|
+
triggers=["api_trigger/test_trigger"],
|
46
56
|
service_account_credentials={...},
|
47
57
|
)
|
48
58
|
|
@@ -63,10 +73,10 @@ class ApplicationIntegrationToolset:
|
|
63
73
|
service_account_credentials={...},
|
64
74
|
)
|
65
75
|
|
66
|
-
#
|
76
|
+
# Feed the toolset to agent
|
67
77
|
agent = LlmAgent(tools=[
|
68
|
-
|
69
|
-
|
78
|
+
...,
|
79
|
+
application_integration_toolset,
|
70
80
|
])
|
71
81
|
```
|
72
82
|
"""
|
@@ -76,100 +86,74 @@ class ApplicationIntegrationToolset:
|
|
76
86
|
project: str,
|
77
87
|
location: str,
|
78
88
|
integration: Optional[str] = None,
|
79
|
-
|
89
|
+
triggers: Optional[List[str]] = None,
|
80
90
|
connection: Optional[str] = None,
|
81
91
|
entity_operations: Optional[str] = None,
|
82
92
|
actions: Optional[str] = None,
|
83
93
|
# Optional parameter for the toolset. This is prepended to the generated
|
84
94
|
# tool/python function name.
|
85
|
-
|
95
|
+
tool_name_prefix: Optional[str] = "",
|
86
96
|
# Optional parameter for the toolset. This is appended to the generated
|
87
97
|
# tool/python function description.
|
88
98
|
tool_instructions: Optional[str] = "",
|
89
99
|
service_account_json: Optional[str] = None,
|
100
|
+
auth_scheme: Optional[AuthScheme] = None,
|
101
|
+
auth_credential: Optional[AuthCredential] = None,
|
102
|
+
tool_filter: Optional[Union[ToolPredicate, List[str]]] = None,
|
90
103
|
):
|
91
|
-
"""
|
92
|
-
|
93
|
-
Example Usage:
|
94
|
-
```
|
95
|
-
# Get all available tools for an integration with api trigger
|
96
|
-
application_integration_toolset = ApplicationIntegrationToolset(
|
97
|
-
|
98
|
-
project="test-project",
|
99
|
-
location="us-central1"
|
100
|
-
integration="test-integration",
|
101
|
-
trigger="api_trigger/test_trigger",
|
102
|
-
service_account_credentials={...},
|
103
|
-
)
|
104
|
-
|
105
|
-
# Get all available tools for a connection using entity operations and
|
106
|
-
# actions
|
107
|
-
# Note: Find the list of supported entity operations and actions for a
|
108
|
-
connection
|
109
|
-
# using integration connector apis:
|
110
|
-
#
|
111
|
-
https://cloud.google.com/integration-connectors/docs/reference/rest/v1/projects.locations.connections.connectionSchemaMetadata
|
112
|
-
application_integration_toolset = ApplicationIntegrationToolset(
|
113
|
-
project="test-project",
|
114
|
-
location="us-central1"
|
115
|
-
connection="test-connection",
|
116
|
-
entity_operations=["EntityId1": ["LIST","CREATE"], "EntityId2": []],
|
117
|
-
#empty list for actions means all operations on the entity are supported
|
118
|
-
actions=["action1"],
|
119
|
-
service_account_credentials={...},
|
120
|
-
)
|
121
|
-
|
122
|
-
# Get all available tools
|
123
|
-
agent = LlmAgent(tools=[
|
124
|
-
...
|
125
|
-
*application_integration_toolset.get_tools(),
|
126
|
-
])
|
127
|
-
```
|
104
|
+
"""Args:
|
128
105
|
|
129
106
|
Args:
|
130
107
|
project: The GCP project ID.
|
131
108
|
location: The GCP location.
|
132
109
|
integration: The integration name.
|
133
|
-
|
110
|
+
triggers: The list of trigger names in the integration.
|
134
111
|
connection: The connection name.
|
135
112
|
entity_operations: The entity operations supported by the connection.
|
136
113
|
actions: The actions supported by the connection.
|
137
|
-
|
114
|
+
tool_name_prefix: The name prefix of the generated tools.
|
138
115
|
tool_instructions: The instructions for the tool.
|
139
116
|
service_account_json: The service account configuration as a dictionary.
|
140
117
|
Required if not using default service credential. Used for fetching
|
141
118
|
the Application Integration or Integration Connector resource.
|
119
|
+
tool_filter: The filter used to filter the tools in the toolset. It can
|
120
|
+
be either a tool predicate or a list of tool names of the tools to
|
121
|
+
expose.
|
142
122
|
|
143
123
|
Raises:
|
144
|
-
ValueError: If
|
145
|
-
|
124
|
+
ValueError: If none of the following conditions are met:
|
125
|
+
- `integration` is provided.
|
126
|
+
- `connection` is provided and at least one of `entity_operations`
|
127
|
+
or `actions` is provided.
|
146
128
|
Exception: If there is an error during the initialization of the
|
147
129
|
integration or connection client.
|
148
130
|
"""
|
149
131
|
self.project = project
|
150
132
|
self.location = location
|
151
|
-
self.
|
152
|
-
self.
|
153
|
-
self.
|
154
|
-
self.
|
155
|
-
self.
|
156
|
-
self.
|
157
|
-
self.
|
158
|
-
self.
|
159
|
-
self.
|
133
|
+
self._integration = integration
|
134
|
+
self._triggers = triggers
|
135
|
+
self._connection = connection
|
136
|
+
self._entity_operations = entity_operations
|
137
|
+
self._actions = actions
|
138
|
+
self._tool_name_prefix = tool_name_prefix
|
139
|
+
self._tool_instructions = tool_instructions
|
140
|
+
self._service_account_json = service_account_json
|
141
|
+
self._auth_scheme = auth_scheme
|
142
|
+
self._auth_credential = auth_credential
|
143
|
+
self.tool_filter = tool_filter
|
160
144
|
|
161
145
|
integration_client = IntegrationClient(
|
162
146
|
project,
|
163
147
|
location,
|
164
148
|
integration,
|
165
|
-
|
149
|
+
triggers,
|
166
150
|
connection,
|
167
151
|
entity_operations,
|
168
152
|
actions,
|
169
153
|
service_account_json,
|
170
154
|
)
|
171
155
|
connection_details = {}
|
172
|
-
if integration
|
156
|
+
if integration:
|
173
157
|
spec = integration_client.get_openapi_spec_for_integration()
|
174
158
|
elif connection and (entity_operations or actions):
|
175
159
|
connections_client = ConnectionsClient(
|
@@ -177,21 +161,23 @@ class ApplicationIntegrationToolset:
|
|
177
161
|
)
|
178
162
|
connection_details = connections_client.get_connection_details()
|
179
163
|
spec = integration_client.get_openapi_spec_for_connection(
|
180
|
-
|
164
|
+
tool_name_prefix,
|
181
165
|
tool_instructions,
|
182
166
|
)
|
183
167
|
else:
|
184
168
|
raise ValueError(
|
185
|
-
"Either
|
169
|
+
"Invalid request, Either integration or (connection and"
|
186
170
|
" (entity_operations or actions)) should be provided."
|
187
171
|
)
|
188
|
-
self.
|
172
|
+
self._openapi_toolset = None
|
173
|
+
self._tools = []
|
174
|
+
self._parse_spec_to_toolset(spec, connection_details)
|
189
175
|
|
190
|
-
def
|
191
|
-
"""Parses the spec dict to
|
192
|
-
if self.
|
176
|
+
def _parse_spec_to_toolset(self, spec_dict, connection_details):
|
177
|
+
"""Parses the spec dict to OpenAPI toolset."""
|
178
|
+
if self._service_account_json:
|
193
179
|
sa_credential = ServiceAccountCredential.model_validate_json(
|
194
|
-
self.
|
180
|
+
self._service_account_json
|
195
181
|
)
|
196
182
|
service_account = ServiceAccount(
|
197
183
|
service_account_credential=sa_credential,
|
@@ -210,14 +196,13 @@ class ApplicationIntegrationToolset:
|
|
210
196
|
)
|
211
197
|
auth_scheme = HTTPBearer(bearerFormat="JWT")
|
212
198
|
|
213
|
-
if self.
|
214
|
-
|
199
|
+
if self._integration:
|
200
|
+
self._openapi_toolset = OpenAPIToolset(
|
215
201
|
spec_dict=spec_dict,
|
216
202
|
auth_credential=auth_credential,
|
217
203
|
auth_scheme=auth_scheme,
|
218
|
-
|
219
|
-
|
220
|
-
self.generated_tools[tool.name] = tool
|
204
|
+
tool_filter=self.tool_filter,
|
205
|
+
)
|
221
206
|
return
|
222
207
|
|
223
208
|
operations = OpenApiSpecParser().parse(spec_dict)
|
@@ -235,18 +220,55 @@ class ApplicationIntegrationToolset:
|
|
235
220
|
rest_api_tool.configure_auth_scheme(auth_scheme)
|
236
221
|
if auth_credential:
|
237
222
|
rest_api_tool.configure_auth_credential(auth_credential)
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
connection_name=connection_details["name"],
|
242
|
-
connection_host=connection_details["host"],
|
243
|
-
connection_service_name=connection_details["serviceName"],
|
244
|
-
entity=entity,
|
245
|
-
action=action,
|
246
|
-
operation=operation,
|
247
|
-
rest_api_tool=rest_api_tool,
|
223
|
+
|
224
|
+
auth_override_enabled = connection_details.get(
|
225
|
+
"authOverrideEnabled", False
|
248
226
|
)
|
249
|
-
self.generated_tools[tool.name] = tool
|
250
227
|
|
251
|
-
|
252
|
-
|
228
|
+
if (
|
229
|
+
self._auth_scheme
|
230
|
+
and self._auth_credential
|
231
|
+
and not auth_override_enabled
|
232
|
+
):
|
233
|
+
# Case: Auth provided, but override is OFF. Don't use provided auth.
|
234
|
+
logger.warning(
|
235
|
+
"Authentication schema and credentials are not used because"
|
236
|
+
" authOverrideEnabled is not enabled in the connection."
|
237
|
+
)
|
238
|
+
connector_auth_scheme = None
|
239
|
+
connector_auth_credential = None
|
240
|
+
else:
|
241
|
+
connector_auth_scheme = self._auth_scheme
|
242
|
+
connector_auth_credential = self._auth_credential
|
243
|
+
|
244
|
+
self._tools.append(
|
245
|
+
IntegrationConnectorTool(
|
246
|
+
name=rest_api_tool.name,
|
247
|
+
description=rest_api_tool.description,
|
248
|
+
connection_name=connection_details["name"],
|
249
|
+
connection_host=connection_details["host"],
|
250
|
+
connection_service_name=connection_details["serviceName"],
|
251
|
+
entity=entity,
|
252
|
+
action=action,
|
253
|
+
operation=operation,
|
254
|
+
rest_api_tool=rest_api_tool,
|
255
|
+
auth_scheme=connector_auth_scheme,
|
256
|
+
auth_credential=connector_auth_credential,
|
257
|
+
)
|
258
|
+
)
|
259
|
+
|
260
|
+
@override
|
261
|
+
async def get_tools(
|
262
|
+
self,
|
263
|
+
readonly_context: Optional[ReadonlyContext] = None,
|
264
|
+
) -> List[RestApiTool]:
|
265
|
+
return (
|
266
|
+
self._tools
|
267
|
+
if self._openapi_toolset is None
|
268
|
+
else await self._openapi_toolset.get_tools(readonly_context)
|
269
|
+
)
|
270
|
+
|
271
|
+
@override
|
272
|
+
async def close(self) -> None:
|
273
|
+
if self._openapi_toolset:
|
274
|
+
await self._openapi_toolset.close()
|
@@ -554,6 +554,9 @@ class ConnectionsClient:
|
|
554
554
|
"serviceName": {"$ref": "#/components/schemas/serviceName"},
|
555
555
|
"host": {"$ref": "#/components/schemas/host"},
|
556
556
|
"entity": {"$ref": "#/components/schemas/entity"},
|
557
|
+
"dynamicAuthConfig": {
|
558
|
+
"$ref": "#/components/schemas/dynamicAuthConfig"
|
559
|
+
},
|
557
560
|
},
|
558
561
|
}
|
559
562
|
|
@@ -580,6 +583,10 @@ class ConnectionsClient:
|
|
580
583
|
"serviceName": {"$ref": "#/components/schemas/serviceName"},
|
581
584
|
"host": {"$ref": "#/components/schemas/host"},
|
582
585
|
"entity": {"$ref": "#/components/schemas/entity"},
|
586
|
+
"dynamicAuthConfig": {
|
587
|
+
"$ref": "#/components/schemas/dynamicAuthConfig"
|
588
|
+
},
|
589
|
+
"filterClause": {"$ref": "#/components/schemas/filterClause"},
|
583
590
|
},
|
584
591
|
}
|
585
592
|
|
@@ -602,6 +609,9 @@ class ConnectionsClient:
|
|
602
609
|
"serviceName": {"$ref": "#/components/schemas/serviceName"},
|
603
610
|
"host": {"$ref": "#/components/schemas/host"},
|
604
611
|
"entity": {"$ref": "#/components/schemas/entity"},
|
612
|
+
"dynamicAuthConfig": {
|
613
|
+
"$ref": "#/components/schemas/dynamicAuthConfig"
|
614
|
+
},
|
605
615
|
},
|
606
616
|
}
|
607
617
|
|
@@ -624,6 +634,10 @@ class ConnectionsClient:
|
|
624
634
|
"serviceName": {"$ref": "#/components/schemas/serviceName"},
|
625
635
|
"host": {"$ref": "#/components/schemas/host"},
|
626
636
|
"entity": {"$ref": "#/components/schemas/entity"},
|
637
|
+
"dynamicAuthConfig": {
|
638
|
+
"$ref": "#/components/schemas/dynamicAuthConfig"
|
639
|
+
},
|
640
|
+
"filterClause": {"$ref": "#/components/schemas/filterClause"},
|
627
641
|
},
|
628
642
|
}
|
629
643
|
|
@@ -647,6 +661,9 @@ class ConnectionsClient:
|
|
647
661
|
"serviceName": {"$ref": "#/components/schemas/serviceName"},
|
648
662
|
"host": {"$ref": "#/components/schemas/host"},
|
649
663
|
"entity": {"$ref": "#/components/schemas/entity"},
|
664
|
+
"dynamicAuthConfig": {
|
665
|
+
"$ref": "#/components/schemas/dynamicAuthConfig"
|
666
|
+
},
|
650
667
|
},
|
651
668
|
}
|
652
669
|
|
@@ -671,6 +688,9 @@ class ConnectionsClient:
|
|
671
688
|
"connectorInputPayload": {
|
672
689
|
"$ref": f"#/components/schemas/connectorInputPayload_{action}"
|
673
690
|
},
|
691
|
+
"dynamicAuthConfig": {
|
692
|
+
"$ref": "#/components/schemas/dynamicAuthConfig"
|
693
|
+
},
|
674
694
|
},
|
675
695
|
}
|
676
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:
|