Skip to content

Commit c95e333

Browse files
authored
Merge branch 'main' into feat/evaluate-full-response
2 parents ee8c179 + e7d8160 commit c95e333

12 files changed

Lines changed: 436 additions & 9 deletions

File tree

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "1.28.0"
2+
".": "1.29.0"
33
}

.github/release-please-config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
3-
"last-release-sha": "50209549206256abe5d1c5d84ab2b14dfdf80d66",
3+
"last-release-sha": "6b1600fbf53bcf634c5fe4793f02921bc0b75125",
44
"packages": {
55
".": {
66
"release-type": "python",

CHANGELOG.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,80 @@
11
# Changelog
22

3+
## [1.29.0](https://github.com/google/adk-python/compare/v1.28.0...v1.29.0) (2026-04-09)
4+
5+
6+
### Features
7+
8+
* Add auth scheme/credential support to MCP toolsets in Agent Registry ([7913a3b](https://github.com/google/adk-python/commit/7913a3b76432caf16953ea7b2a2cf4872baad417))
9+
* add ability to block shell metacharacters in BashTool ([23bd95b](https://github.com/google/adk-python/commit/23bd95bcf23367a8df3342ca4bb9d17f0b3b0d8f))
10+
* add configurable resource limits for subprocesses in BashTool ([1b05842](https://github.com/google/adk-python/commit/1b0584241f6418fd5fe9bd05fa666d03c310b8ae))
11+
* Add configurable view_prefix to BigQueryLoggerConfig ([37973da](https://github.com/google/adk-python/commit/37973daff47d3c67e928a240acd188d4e318f52b))
12+
* Add custom session id functionality to vertex ai session service ([e1913a6](https://github.com/google/adk-python/commit/e1913a6b411aec9e8774ca92ea39531b085c43f0))
13+
* Add Description column to SKILL.md and update terminology ([435f7c7](https://github.com/google/adk-python/commit/435f7c7a9fdf8b1214f4439c6d953b6426d90da1))
14+
* Add Easy GCP support to ADK CLI ([8850916](https://github.com/google/adk-python/commit/8850916e1908ace19a058102f0392eee08349d60))
15+
* Add regional endpoint support to `SecretManagerClient` ([19ac679](https://github.com/google/adk-python/commit/19ac679aeacc045ed78cb9fd48bb295440843288))
16+
* Add support for model endpoints in Agent Registry ([eb4674b](https://github.com/google/adk-python/commit/eb4674b49f017f3947506c55be4075b1ea0369d6))
17+
* **auth:** Add public api to register custom auth provider with credential manager ([a220910](https://github.com/google/adk-python/commit/a22091058dd2ea6e1e0655b5946ce6ed7e72d25e))
18+
* **auth:** Pass consent_nonce to Agent Frontend ([9fec503](https://github.com/google/adk-python/commit/9fec503061846b9903c18921f7848b358a041331))
19+
* **auth:** Support additional HTTP headers in MCP tools ([b3e9962](https://github.com/google/adk-python/commit/b3e99628ee1b87b61badf56e67f8ddee15e6fe54))
20+
* **bigquery:** Add ADK 1P Skills for ADK BQ Toolset ([4030c0d](https://github.com/google/adk-python/commit/4030c0d0167b348cf2e4c941c8610aa6ede28275))
21+
* **environment:** Add EnvironmentToolset for file I/O and command execution ([9082b9e](https://github.com/google/adk-python/commit/9082b9e38eeb3465c399b41633e6441e339c47c3))
22+
* **environment:** Add LocalEnvironment for executing commands and file I/O locally ([f973673](https://github.com/google/adk-python/commit/f97367381e820c75ad16d4ce7ee27c0f9929c81d))
23+
* Implement robust process group management and timeouts in BashTool ([f641b1a](https://github.com/google/adk-python/commit/f641b1a219b041659e6d429c47974bc9e5cfe1af))
24+
* **live:** Added in 1.28.1, support live for `gemini-3.1-flash-live-preview` model ([8082893](https://github.com/google/adk-python/commit/8082893619bb85d4ee0dc53fd2133d12b9434d07))
25+
* Option to use shallow-copy for session in InMemorySessionService ([16a1a18](https://github.com/google/adk-python/commit/16a1a185ab77a904fd01712779fa1bc6417dc628))
26+
* Propagate context to thread pools ([83393ab](https://github.com/google/adk-python/commit/83393ab839d5733568699195683408fccbd1cb6e))
27+
* refresh credentials if token is missing in the common code and samples ([1445ad5](https://github.com/google/adk-python/commit/1445ad5069841e446328e0856553f69a6699f0f4))
28+
* Remove use of raw_event field in vertex ai session service ([642d337](https://github.com/google/adk-python/commit/642d337a9069fae334192d045c9f85922cbcef53))
29+
* **skill:** Standardize skill tools and make script arguments flexible ([9e73ab8](https://github.com/google/adk-python/commit/9e73ab846672065f1fbe1c2642419e8a008efd43))
30+
* Support AgentRegistry association ([6754760](https://github.com/google/adk-python/commit/675476088b9f3c0a488ce48f652b7f3f7ea47230))
31+
* Support loading agents from Visual Builder with BigQuery-powered logging ([2074889](https://github.com/google/adk-python/commit/20748894cdaa5a95d0c4ccb0daf87a34496639dd))
32+
* Support propagating grounding metadata from AgentTool ([d689a04](https://github.com/google/adk-python/commit/d689a04f16846c2aa483dd45dcc65e2decdb419c))
33+
* Support short options and positional arguments in RunSkillScriptTool ([2b49163](https://github.com/google/adk-python/commit/2b49163b399135f0d96b73a99eb4ace764ce87db))
34+
* Use raw_event field in vertex ai session service for append and list events ([6ee0362](https://github.com/google/adk-python/commit/6ee036292e9eefabb032e8ebec3580a2243f3a96))
35+
* Use raw_event to store event data in vertex ai session service ([9da9dee](https://github.com/google/adk-python/commit/9da9dee140a3c8971d2dc267eab7d8d17a22a089))
36+
37+
38+
### Bug Fixes
39+
40+
* Add A2ATransport.http_json to the default supported transports list ([7dd9359](https://github.com/google/adk-python/commit/7dd9359fa1c419f82db84b844195e1b77d8070e7))
41+
* add httpx_client_factory support to SseConnectionParams ([815ebb4](https://github.com/google/adk-python/commit/815ebb441579724e5aa22830b2e6f7c22f94fde6))
42+
* **adk:** redact credentials in BigQuery analytics plugin ([a27ce47](https://github.com/google/adk-python/commit/a27ce4771ff271947a0d94762231da842095836e))
43+
* api client initialization logic to be mutually exclusive between ExpressMode and GCP projects ([4ffe8fb](https://github.com/google/adk-python/commit/4ffe8fb4a6befc9e9d0e838427b7bf4890df4ba3))
44+
* avoid load all agents in adk web server ([ede8a56](https://github.com/google/adk-python/commit/ede8a56a3cd18311ce82e761f0f3da6228fbc0d6))
45+
* Cache BaseToolset.get_tools() for calls within the same invocation ([92cad99](https://github.com/google/adk-python/commit/92cad99724d333760e4ebc6116951d78a9b1cb7a))
46+
* **cli:** fail Agent Engine deploy when config file path is invalid ([bbad9ec](https://github.com/google/adk-python/commit/bbad9ec64ce1617bc45148de97e6246752845b98))
47+
* Disable tool caching for skill toolset ([064f0d2](https://github.com/google/adk-python/commit/064f0d278e55e1e9fd6db1b6ccf3d1cb95cba47b))
48+
* Disallow args on /builder and Add warning about Web UI usage to CLI help ([dcee290](https://github.com/google/adk-python/commit/dcee2902729e178b41086c4039a3828917bbb9f3))
49+
* empty events_iterator assignment ([898c4e5](https://github.com/google/adk-python/commit/898c4e5f78b60c4c4732c7cd19ff2da9a64964a1))
50+
* **environment:** fix package references ([add8e86](https://github.com/google/adk-python/commit/add8e8664bd2ae9257c8b37a5e602d0c7aae7625))
51+
* Fix RemoteA2AAgent deepcopy errors ([6f29775](https://github.com/google/adk-python/commit/6f29775f4bf7172b1378b17856534f95b9d4eeb6))
52+
* Fixes for initializing RemoteA2aAgent - passing in preferred transport, protocol version, and auth headers ([0f3850f](https://github.com/google/adk-python/commit/0f3850f56c857dfb86c7ad8de372bcc7fe495968))
53+
* Generate IDs for FunctionCalls when processing streaming LLM responses ([fe41817](https://github.com/google/adk-python/commit/fe4181718d104843b974417c59203ed8a7b15255)), closes [#4609](https://github.com/google/adk-python/issues/4609)
54+
* Handle merging lists in deep_merge_dicts ([cdb3ff4](https://github.com/google/adk-python/commit/cdb3ff4e1f155c357f8cf720132d09bbc1446075))
55+
* In memory session service to evaluate dictionary keys and value into an isolated snapshot sequence before starting loop ([f75de59](https://github.com/google/adk-python/commit/f75de59362e07c0cce0ead723ceea3102081af4d))
56+
* include intermediate subagent final response events in evaluation intermediate data ([f8a6bd7](https://github.com/google/adk-python/commit/f8a6bd7fc0ca4b37cac4dc93c725c8973a1c9027))
57+
* **live:** Handle live session resumption and GoAway signal ([6b1600f](https://github.com/google/adk-python/commit/6b1600fbf53bcf634c5fe4793f02921bc0b75125)), closes [#4996](https://github.com/google/adk-python/issues/4996)
58+
* move BigQueryAgentAnalyticsPlugin import inside get_runner_async ([6fd0f85](https://github.com/google/adk-python/commit/6fd0f85191dea17b7c6b033473bd39764250265b))
59+
* Safer fix for UI widget merging in ADK ([0e71985](https://github.com/google/adk-python/commit/0e71985501c00682eff0f0c5328a3d429f2bdc68))
60+
* Small fixes for express mode ([3a374ce](https://github.com/google/adk-python/commit/3a374ce0aae73c138cd51d754220d0d7a64677b3))
61+
* sync callbacks with call_llm span ([b2daf83](https://github.com/google/adk-python/commit/b2daf83db406f8844f9db75abc7fee17362433b3))
62+
* **tools:** handle toolset errors gracefully in canonical_tools ([5df03f1](https://github.com/google/adk-python/commit/5df03f1f412e3ab55a5a6ceac892ba6b985a8036)), closes [#3341](https://github.com/google/adk-python/issues/3341)
63+
* truncate error_message in v0 schema to prevent VARCHAR overflow ([62daf4f](https://github.com/google/adk-python/commit/62daf4f61b14aee7bca9d8dec479bfd940bbb955)), closes [#4993](https://github.com/google/adk-python/issues/4993)
64+
* update toolbox-adk and toolbox server versions ([1486925](https://github.com/google/adk-python/commit/14869253d072e901d530fd3b7ee8ef67fbe5ddbc))
65+
66+
67+
### Code Refactoring
68+
69+
* Move SecretManagerClient to google.adk.integrations.secret_manager package ([1104523](https://github.com/google/adk-python/commit/110452375c6ccaa16e4ade7d7fe3438d185d4355))
70+
* Remove the session events dependency from A2aAgentExecutor ([aaa03ac](https://github.com/google/adk-python/commit/aaa03ac30841b2e12e3ddf4bb02fbcbf08ae13e8))
71+
72+
73+
### Documentation
74+
75+
* **adk:** clean up remote triggers README to remove internal references ([ccac461](https://github.com/google/adk-python/commit/ccac461b2ab6291ecd09577ca0553833eaff71b9))
76+
* Update the MCP Toolbox docsite with the new URL ([a60baca](https://github.com/google/adk-python/commit/a60baca3ddfe2541159b32d67b738a836d2395e7))
77+
378
## [1.28.0](https://github.com/google/adk-python/compare/v1.27.5...v1.28.0) (2026-03-26)
479

580

src/google/adk/cli/cli_create.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,27 @@ def _handle_login_with_google() -> (
378378
f"Express Mode project created: {project_id}",
379379
fg="green",
380380
)
381+
current_proj = _get_gcp_project_from_gcloud()
382+
if current_proj and current_proj != project_id:
383+
click.secho(
384+
"Warning: Your default gcloud project is set to"
385+
f" '{current_proj}'. This might conflict with or override your"
386+
f" Express Mode project '{project_id}'. We recommend"
387+
" unsetting it.",
388+
fg="yellow",
389+
)
390+
if click.confirm("Run 'gcloud config unset project'?", default=True):
391+
try:
392+
subprocess.run(
393+
["gcloud", "config", "unset", "project"],
394+
check=True,
395+
capture_output=True,
396+
)
397+
click.secho("Unset default gcloud project.", fg="green")
398+
except Exception:
399+
click.secho(
400+
"Failed to unset project. Please do it manually.", fg="red"
401+
)
381402
return api_key, project_id, region
382403

383404
click.secho(_NOT_ELIGIBLE_MSG, fg="red")

src/google/adk/flows/llm_flows/base_llm_flow.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,7 @@ def get_author_for_event(llm_response):
755755
# We proactively raise ConnectionClosed to trigger the reconnection
756756
# logic in run_live, which will use the latest session handle.
757757
raise ConnectionClosed(None, None)
758+
758759
model_response_event = Event(
759760
id=Event.new_id(),
760761
invocation_id=invocation_context.invocation_id,
@@ -1020,9 +1021,18 @@ async def _postprocess_live(
10201021
and not llm_response.input_transcription
10211022
and not llm_response.output_transcription
10221023
and not llm_response.usage_metadata
1024+
and not llm_response.live_session_resumption_update
10231025
):
10241026
return
10251027

1028+
# Handle session resumption updates for cross-connection resumption
1029+
if llm_response.live_session_resumption_update:
1030+
model_response_event.live_session_resumption_update = (
1031+
llm_response.live_session_resumption_update
1032+
)
1033+
yield model_response_event
1034+
return
1035+
10261036
# Handle transcription events ONCE per llm_response, outside the event loop
10271037
if llm_response.input_transcription:
10281038
model_response_event.input_transcription = (

src/google/adk/models/gemma_llm.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,8 @@ class GemmaFunctionCallModel(BaseModel):
163163
class Gemma(GemmaFunctionCallingMixin, Gemini):
164164
"""Integration for Gemma models exposed via the Gemini API.
165165
166-
Only Gemma 3 models are supported at this time. For agentic use cases,
167-
use of gemma-3-27b-it and gemma-3-12b-it are strongly recommended.
166+
For agentic use cases, use of gemma-3-27b-it, gemma-3-12b-it, and
167+
gemma-4-31b-it are strongly recommended.
168168
169169
For full documentation, see: https://ai.google.dev/gemma/docs/core/
170170
@@ -205,7 +205,7 @@ def supported_models(cls) -> list[str]:
205205
"""
206206

207207
return [
208-
r'gemma-3.*',
208+
r'gemma-.*',
209209
]
210210

211211
@cached_property

src/google/adk/models/interactions_utils.py

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,36 @@
5656
_NEW_LINE = '\n'
5757

5858

59+
def _extract_stream_interaction_id(
60+
event: 'InteractionSSEEvent',
61+
) -> Optional[str]:
62+
"""Extract the interaction ID from an Interactions SSE event.
63+
64+
Different SSE lifecycle events expose the interaction ID on different
65+
attributes. We normalize them here so streamed ADK responses consistently
66+
carry the chain identifier needed for follow-up tool calls. Older
67+
google-genai builds may also yield a legacy ``interaction`` event with a
68+
top-level ``id``.
69+
"""
70+
from google.genai._interactions.types.interaction_complete_event import InteractionCompleteEvent
71+
from google.genai._interactions.types.interaction_start_event import InteractionStartEvent
72+
from google.genai._interactions.types.interaction_status_update import InteractionStatusUpdate
73+
74+
if isinstance(event, InteractionStatusUpdate):
75+
return event.interaction_id
76+
77+
if isinstance(event, (InteractionStartEvent, InteractionCompleteEvent)):
78+
return event.interaction.id
79+
80+
try:
81+
if event.event_type == 'interaction':
82+
return event.id
83+
except AttributeError:
84+
pass
85+
86+
return None
87+
88+
5989
def convert_part_to_interaction_content(part: types.Part) -> Optional[dict]:
6090
"""Convert a types.Part to an interaction content dict.
6191
@@ -1013,9 +1043,9 @@ async def generate_content_via_interactions(
10131043
# Log the streaming event
10141044
logger.debug(build_interactions_event_log(event))
10151045

1016-
# Extract interaction ID from event if available
1017-
if hasattr(event, 'id') and event.id:
1018-
current_interaction_id = event.id
1046+
interaction_id = _extract_stream_interaction_id(event)
1047+
if interaction_id:
1048+
current_interaction_id = interaction_id
10191049
llm_response = convert_interaction_event_to_llm_response(
10201050
event, aggregated_parts, current_interaction_id
10211051
)

src/google/adk/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313
# limitations under the License.
1414

1515
# version: major.minor.patch
16-
__version__ = "1.28.0"
16+
__version__ = "1.29.0"

tests/unittests/cli/utils/test_cli_create.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,52 @@ def test_handle_login_with_google_option_2(
417417
assert region == "us-central1"
418418

419419

420+
def test_handle_login_with_google_option_2_unset_project(
421+
monkeypatch: pytest.MonkeyPatch,
422+
) -> None:
423+
"""User selects 2, goes through express sign up, and unsets existing gcloud project."""
424+
monkeypatch.setattr(gcp_utils, "check_adc", lambda: True)
425+
monkeypatch.setattr(gcp_utils, "retrieve_express_project", lambda: None)
426+
monkeypatch.setattr(gcp_utils, "list_gcp_projects", lambda limit: [])
427+
monkeypatch.setattr(gcp_utils, "check_express_eligibility", lambda: True)
428+
429+
confirms = iter([True, True])
430+
monkeypatch.setattr(click, "confirm", lambda *a, **k: next(confirms))
431+
432+
prompts = iter(["2", "1"])
433+
monkeypatch.setattr(click, "prompt", lambda *a, **k: next(prompts))
434+
435+
monkeypatch.setattr(
436+
gcp_utils,
437+
"sign_up_express",
438+
lambda location="us-central1": {
439+
"api_key": "new-key",
440+
"project_id": "new-proj",
441+
"region": location,
442+
},
443+
)
444+
445+
monkeypatch.setattr(
446+
cli_create, "_get_gcp_project_from_gcloud", lambda: "old-proj"
447+
)
448+
449+
called = {}
450+
451+
def fake_run(cmd, **kwargs):
452+
if cmd == ["gcloud", "config", "unset", "project"]:
453+
called["unset"] = True
454+
return subprocess.CompletedProcess(args=cmd, returncode=0)
455+
raise ValueError(f"Unexpected command: {cmd}")
456+
457+
monkeypatch.setattr(subprocess, "run", fake_run)
458+
459+
api_key, proj, region = cli_create._handle_login_with_google()
460+
assert api_key == "new-key"
461+
assert proj == "new-proj"
462+
assert region == "us-central1"
463+
assert called.get("unset") is True
464+
465+
420466
def test_handle_login_with_google_option_3(
421467
monkeypatch: pytest.MonkeyPatch,
422468
) -> None:

tests/unittests/flows/llm_flows/test_base_llm_flow.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,3 +893,35 @@ async def mock_receive():
893893
# We expect 2 successful attempts + DEFAULT_MAX_RECONNECT_ATTEMPTS failed attempts
894894
# Total calls = 2 + 5 = 7
895895
assert mock_connect.call_count == DEFAULT_MAX_RECONNECT_ATTEMPTS + 2
896+
897+
898+
@pytest.mark.asyncio
899+
async def test_postprocess_live_session_resumption_update():
900+
"""Test that _postprocess_live yields live_session_resumption_update."""
901+
agent = Agent(name='test_agent')
902+
invocation_context = await testing_utils.create_invocation_context(
903+
agent=agent
904+
)
905+
flow = BaseLlmFlowForTesting()
906+
907+
llm_request = LlmRequest()
908+
llm_response = LlmResponse(
909+
live_session_resumption_update=types.LiveServerSessionResumptionUpdate(
910+
new_handle='test_handle'
911+
)
912+
)
913+
model_response_event = Event(
914+
id=Event.new_id(),
915+
invocation_id=invocation_context.invocation_id,
916+
author=agent.name,
917+
)
918+
919+
events = []
920+
async for event in flow._postprocess_live(
921+
invocation_context, llm_request, llm_response, model_response_event
922+
):
923+
events.append(event)
924+
925+
assert len(events) == 1
926+
assert events[0].live_session_resumption_update is not None
927+
assert events[0].live_session_resumption_update.new_handle == 'test_handle'

0 commit comments

Comments
 (0)