Skip to content

Commit 20988cd

Browse files
authored
Merge branch 'main' into fix-thought-signature-pruning
2 parents 355c8e3 + a562a31 commit 20988cd

9 files changed

Lines changed: 561 additions & 120 deletions

File tree

contributing/samples/adk_team/adk_pr_triaging_agent/agent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ def list_untriaged_pull_requests(pr_count: int) -> dict[str, Any]:
236236
query = f"repo:{OWNER}/{REPO} is:open is:pr"
237237
params = {
238238
"q": query,
239-
"sort": "created",
239+
"sort": "updated",
240240
"order": "desc",
241241
"per_page": 100,
242242
"page": 1,

src/google/adk/cli/cli_tools_click.py

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2000,7 +2000,6 @@ def cli_api_server(
20002000
"cloud_run",
20012001
context_settings={
20022002
"allow_extra_args": True,
2003-
"allow_interspersed_args": False,
20042003
},
20052004
)
20062005
@click.option(
@@ -2177,34 +2176,7 @@ def cli_deploy_cloud_run(
21772176

21782177
_warn_if_with_ui(with_ui)
21792178

2180-
# Parse arguments to separate gcloud args (after --) from regular args
2181-
gcloud_args = []
2182-
if "--" in ctx.args:
2183-
separator_index = ctx.args.index("--")
2184-
gcloud_args = ctx.args[separator_index + 1 :]
2185-
regular_args = ctx.args[:separator_index]
2186-
2187-
# If there are regular args before --, that's an error
2188-
if regular_args:
2189-
click.secho(
2190-
"Error: Unexpected arguments after agent path and before '--':"
2191-
f" {' '.join(regular_args)}. \nOnly arguments after '--' are passed"
2192-
" to gcloud.",
2193-
fg="red",
2194-
err=True,
2195-
)
2196-
ctx.exit(2)
2197-
else:
2198-
# No -- separator, treat all args as an error to enforce the new behavior
2199-
if ctx.args:
2200-
click.secho(
2201-
f"Error: Unexpected arguments: {' '.join(ctx.args)}. \nUse '--' to"
2202-
" separate gcloud arguments, e.g.: adk deploy cloud_run [options]"
2203-
" agent_path -- --min-instances=2",
2204-
fg="red",
2205-
err=True,
2206-
)
2207-
ctx.exit(2)
2179+
gcloud_args = ctx.args
22082180

22092181
try:
22102182
from . import cli_deploy

src/google/adk/integrations/parameter_manager/parameter_client.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,17 @@
2626
from google.oauth2 import service_account
2727

2828
from ... import version
29+
from ...utils import mtls_utils
2930

3031
USER_AGENT = f"google-adk/{version.__version__}"
3132

33+
_DEFAULT_REGIONAL_ENDPOINT_TEMPLATE = (
34+
"parametermanager.{location}.rep.googleapis.com"
35+
)
36+
_DEFAULT_MTLS_REGIONAL_ENDPOINT_TEMPLATE = (
37+
"parametermanager.{location}.rep.mtls.googleapis.com"
38+
)
39+
3240

3341
class ParameterManagerClient:
3442
"""A client for interacting with Google Cloud Parameter Manager.
@@ -113,7 +121,11 @@ def __init__(
113121
client_options = None
114122
if location:
115123
client_options = {
116-
"api_endpoint": f"parametermanager.{location}.rep.googleapis.com"
124+
"api_endpoint": mtls_utils.get_api_endpoint(
125+
location,
126+
_DEFAULT_REGIONAL_ENDPOINT_TEMPLATE,
127+
_DEFAULT_MTLS_REGIONAL_ENDPOINT_TEMPLATE,
128+
)
117129
}
118130

119131
self._client = parametermanager_v1.ParameterManagerClient(

src/google/adk/models/interactions_utils.py

Lines changed: 62 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,53 @@ def _get_latest_user_contents(
11661166
return latest_user_contents
11671167

11681168

1169+
async def _create_interactions(
1170+
api_client: Client,
1171+
*,
1172+
create_kwargs: dict[str, Any],
1173+
stream: bool,
1174+
) -> AsyncGenerator[LlmResponse, None]:
1175+
"""Issue ``interactions.create`` and convert the response(s) to LlmResponses.
1176+
1177+
This is the shared transport + conversion loop. The caller assembles
1178+
``create_kwargs`` (``model`` or ``agent``, ``input``, ``tools``, etc.); this
1179+
helper owns issuing the call and mapping the stream to ``LlmResponse``s.
1180+
1181+
Args:
1182+
api_client: The Google GenAI client.
1183+
create_kwargs: Keyword arguments passed verbatim to
1184+
``api_client.aio.interactions.create`` (excluding ``stream``).
1185+
stream: Whether to stream the response.
1186+
1187+
Yields:
1188+
LlmResponse objects converted from interaction responses.
1189+
"""
1190+
current_interaction_id: str | None = None
1191+
1192+
if stream:
1193+
responses = await api_client.aio.interactions.create(
1194+
**create_kwargs, stream=True
1195+
)
1196+
aggregated_parts: list[types.Part] = []
1197+
async for event in responses:
1198+
logger.debug(build_interactions_event_log(event))
1199+
interaction_id = _extract_stream_interaction_id(event)
1200+
if interaction_id:
1201+
current_interaction_id = interaction_id
1202+
llm_response = convert_interaction_event_to_llm_response(
1203+
event, aggregated_parts, current_interaction_id
1204+
)
1205+
if llm_response:
1206+
yield llm_response
1207+
else:
1208+
interaction = await api_client.aio.interactions.create(
1209+
**create_kwargs, stream=False
1210+
)
1211+
logger.info('Interaction response received.')
1212+
logger.debug(build_interactions_response_log(interaction))
1213+
yield convert_interaction_to_llm_response(interaction)
1214+
1215+
11691216
async def generate_content_via_interactions(
11701217
api_client: Client,
11711218
llm_request: LlmRequest,
@@ -1227,49 +1274,18 @@ async def generate_content_via_interactions(
12271274
)
12281275
)
12291276

1230-
# Track the current interaction ID from responses
1231-
current_interaction_id: str | None = None
1232-
1233-
if stream:
1234-
# Streaming mode
1235-
responses = await api_client.aio.interactions.create(
1236-
model=llm_request.model,
1237-
input=input_steps,
1238-
stream=True,
1239-
system_instruction=system_instruction,
1240-
tools=interaction_tools if interaction_tools else None,
1241-
generation_config=generation_config if generation_config else None,
1242-
previous_interaction_id=previous_interaction_id,
1243-
)
1244-
1245-
aggregated_parts: list[types.Part] = []
1246-
async for event in responses:
1247-
# Log the streaming event
1248-
logger.debug(build_interactions_event_log(event))
1249-
1250-
interaction_id = _extract_stream_interaction_id(event)
1251-
if interaction_id:
1252-
current_interaction_id = interaction_id
1253-
llm_response = convert_interaction_event_to_llm_response(
1254-
event, aggregated_parts, current_interaction_id
1255-
)
1256-
if llm_response:
1257-
yield llm_response
1258-
1259-
else:
1260-
# Non-streaming mode
1261-
interaction = await api_client.aio.interactions.create(
1262-
model=llm_request.model,
1263-
input=input_steps,
1264-
stream=False,
1265-
system_instruction=system_instruction,
1266-
tools=interaction_tools if interaction_tools else None,
1267-
generation_config=generation_config if generation_config else None,
1268-
previous_interaction_id=previous_interaction_id,
1269-
)
1270-
1271-
# Log the response
1272-
logger.info('Interaction response received from the model.')
1273-
logger.debug(build_interactions_response_log(interaction))
1274-
1275-
yield convert_interaction_to_llm_response(interaction)
1277+
# Assemble the create() kwargs for the model path and delegate the
1278+
# transport + conversion loop to the shared helper.
1279+
create_kwargs: dict[str, Any] = {
1280+
'model': llm_request.model,
1281+
'input': input_steps,
1282+
'system_instruction': system_instruction,
1283+
'tools': interaction_tools if interaction_tools else None,
1284+
'generation_config': generation_config if generation_config else None,
1285+
'previous_interaction_id': previous_interaction_id,
1286+
}
1287+
1288+
async for llm_response in _create_interactions(
1289+
api_client, create_kwargs=create_kwargs, stream=stream
1290+
):
1291+
yield llm_response

src/google/adk/utils/mtls_utils.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Copyright 2026 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+
"""Utilities for mTLS regional endpoint resolution."""
16+
17+
from __future__ import annotations
18+
19+
import enum
20+
import os
21+
22+
from google.auth.transport import mtls
23+
24+
25+
class MtlsEndpoint(enum.Enum):
26+
"""Enum for the mTLS endpoint setting."""
27+
28+
AUTO = "auto"
29+
ALWAYS = "always"
30+
NEVER = "never"
31+
32+
33+
def use_client_cert_effective() -> bool:
34+
"""Returns whether client certificate should be used for mTLS."""
35+
try:
36+
return mtls.should_use_client_cert()
37+
except (ImportError, AttributeError):
38+
return (
39+
os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false").lower()
40+
== "true"
41+
)
42+
43+
44+
def get_api_endpoint(
45+
location: str, default_template: str, mtls_template: str
46+
) -> str:
47+
"""Returns API endpoint based on mTLS configuration and cert availability.
48+
49+
Args:
50+
location: The region location.
51+
default_template: Template for default regional endpoint (e.g.
52+
"secretmanager.{location}.rep.googleapis.com").
53+
mtls_template: Template for mTLS regional endpoint (e.g.
54+
"secretmanager.{location}.rep.mtls.googleapis.com").
55+
"""
56+
use_mtls_endpoint_str = os.getenv(
57+
"GOOGLE_API_USE_MTLS_ENDPOINT", MtlsEndpoint.AUTO.value
58+
).lower()
59+
try:
60+
use_mtls_endpoint = MtlsEndpoint(use_mtls_endpoint_str)
61+
except ValueError:
62+
use_mtls_endpoint = MtlsEndpoint.AUTO
63+
64+
if (use_mtls_endpoint == MtlsEndpoint.ALWAYS) or (
65+
use_mtls_endpoint == MtlsEndpoint.AUTO and use_client_cert_effective()
66+
):
67+
return mtls_template.format(location=location)
68+
return default_template.format(location=location)

0 commit comments

Comments
 (0)