Skip to content

Commit a23a2dd

Browse files
authored
Merge branch 'main' into wjy/fix-interrupted
2 parents 2f69d66 + 5578772 commit a23a2dd

33 files changed

Lines changed: 2022 additions & 772 deletions
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "1.30.0"
2+
".": "1.31.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": "80a7ecf4b31e4c6de4a1425b03422f384c1a032d",
3+
"last-release-sha": "d69477f6ff348311e1d53e3f2c389dcf037fb049",
44
"packages": {
55
".": {
66
"release-type": "python",

CHANGELOG.md

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

3+
## [1.31.0](https://github.com/google/adk-python/compare/v1.30.0...v1.31.0) (2026-04-16)
4+
5+
6+
### Features
7+
8+
* Add "google-adk" user agent to Parameter Manager and Secret Manager clients ([b8e8f6b](https://github.com/google/adk-python/commit/b8e8f6b90290e48e134f48bbe7e2b800276e7269))
9+
* Add support for memories.ingest_events in VertexAiMemoryBankService ([d69477f](https://github.com/google/adk-python/commit/d69477f6ff348311e1d53e3f2c389dcf037fb049))
10+
* Add Vertex AI Agent Engine Sandbox integration for computer use ([7686848](https://github.com/google/adk-python/commit/76868485519090c5fa2a0287bccca040e438d94e))
11+
* Firestore support ([1a9df8f](https://github.com/google/adk-python/commit/1a9df8f77410a08a85d04744f199d25f20d55ebd))
12+
* **live:** Add live_session_id to LlmResponse ([bf84e2c](https://github.com/google/adk-python/commit/bf84e2cee84f04c886914eb72318875f3c29ea13))
13+
14+
15+
### Bug Fixes
16+
17+
* Bump minimum mcp version from 1.23.0 to 1.24.0 ([494c360](https://github.com/google/adk-python/commit/494c360b2a82af5130f153ff615f84e4c2604a73))
18+
* **cli:** correct console URL path after adk deploy agent_engine ([64ed1a6](https://github.com/google/adk-python/commit/64ed1a68c98e32d61aff43857fa4e756b129b13f)), closes [#5336](https://github.com/google/adk-python/issues/5336)
19+
* execute on_event_callback before append_event to persist plugin modifications ([454188d](https://github.com/google/adk-python/commit/454188de5de0ef44adb7716230eacddcb060dab2)), closes [#3990](https://github.com/google/adk-python/issues/3990)
20+
* make `_EvalMetricResultWithInvocation.expected_invocation` `Optional` for conversation_scenario support ([#5215](https://github.com/google/adk-python/issues/5215)) ([a4c9387](https://github.com/google/adk-python/commit/a4c938775764794f42e00a89e3cb33da5119c38b))
21+
* Pass in auth headers with header provider instead of connection params ([e12b0af](https://github.com/google/adk-python/commit/e12b0af20d9a025e3d75f309de836b139b6d3e88))
22+
* populate required fields in FunctionDeclaration json_schema fallback ([9b9faa4](https://github.com/google/adk-python/commit/9b9faa4ba21d566252e4c25bd55ab9db2658051e))
23+
* Resolve BigQuery plugin issues with A2A transfers, spans, and metadata ([9ca8c38](https://github.com/google/adk-python/commit/9ca8c384324e07e945146359f21010b438eb1bc6))
24+
* upgrade google-genai lower bound ([8bc5728](https://github.com/google/adk-python/commit/8bc57283f3c584a5a6d6d774a316fe63342ed481))
25+
26+
27+
### Code Refactoring
28+
29+
* **live:** Use `send_client_content` to send conversation history ([67dc2eb](https://github.com/google/adk-python/commit/67dc2ebfd42f175f2dd6ea58df51a03c575062c6))
30+
* **live:** Use `send_tool_response` for function responses ([70c5fc8](https://github.com/google/adk-python/commit/70c5fc83a62d1e81d20986223f5c275b086f9822))
31+
32+
33+
### Documentation
34+
35+
* update MCP Toolbox branding, binary version, and asset references ([47fa7b7](https://github.com/google/adk-python/commit/47fa7b743c37e3aa8302e78be552876c2784e6ff))
36+
337
## [1.30.0](https://github.com/google/adk-python/compare/v1.29.0...v1.30.0) (2026-04-13)
438

539

contributing/samples/adk_triaging_agent/agent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"models": "xuanyang15",
3838
"services": "DeanChensj",
3939
"tools": "xuanyang15",
40-
"tracing": "jawoszek",
40+
"tracing": "mhenc",
4141
"web": "wyf7107",
4242
"workflow": "DeanChensj",
4343
}

src/google/adk/agents/invocation_context.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from ..apps.app import EventsCompactionConfig
2929
from ..apps.app import ResumabilityConfig
3030
from ..artifacts.base_artifact_service import BaseArtifactService
31+
from ..auth.auth_credential import AuthCredential
3132
from ..auth.credential_service.base_credential_service import BaseCredentialService
3233
from ..events.event import Event
3334
from ..memory.base_memory_service import BaseMemoryService
@@ -214,6 +215,9 @@ class InvocationContext(BaseModel):
214215
canonical_tools_cache: Optional[list[BaseTool]] = None
215216
"""The cache of canonical tools for this invocation."""
216217

218+
credential_by_key: dict[str, AuthCredential] = Field(default_factory=dict)
219+
"""The resolved credentials for this invocation, keyed by credential_key."""
220+
217221
_invocation_cost_manager: _InvocationCostManager = PrivateAttr(
218222
default_factory=_InvocationCostManager
219223
)

src/google/adk/agents/readonly_context.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
if TYPE_CHECKING:
2323
from google.genai import types
2424

25+
from ..auth.auth_credential import AuthCredential
2526
from ..sessions.session import Session
2627
from .invocation_context import InvocationContext
2728
from .run_config import RunConfig
@@ -69,3 +70,7 @@ def user_id(self) -> str:
6970
def run_config(self) -> Optional[RunConfig]:
7071
"""The run config of the current invocation. READONLY field."""
7172
return self._invocation_context.run_config
73+
74+
def get_credential(self, key: str) -> Optional[AuthCredential]:
75+
"""Gets a resolved credential by key for this invocation."""
76+
return self._invocation_context.credential_by_key.get(key)

src/google/adk/cli/adk_web_server.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2075,6 +2075,7 @@ async def run_agent_live(
20752075
proactive_audio: bool | None = Query(default=None),
20762076
enable_affective_dialog: bool | None = Query(default=None),
20772077
enable_session_resumption: bool | None = Query(default=None),
2078+
save_live_blob: bool = Query(default=False),
20782079
) -> None:
20792080
ws_origin = websocket.headers.get("origin")
20802081
if ws_origin is not None and not _is_request_origin_allowed(
@@ -2117,6 +2118,7 @@ async def forward_events():
21172118
if enable_session_resumption is not None
21182119
else None
21192120
),
2121+
save_live_blob=save_live_blob,
21202122
)
21212123
async with Aclosing(
21222124
runner.run_live(

src/google/adk/environment/_local_environment.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -123,23 +123,24 @@ async def execute(
123123
)
124124

125125
@override
126-
async def read_file(self, path: str) -> bytes:
126+
async def read_file(self, path: str | Path) -> bytes:
127127
if self._working_dir is None:
128128
raise RuntimeError('`working_dir` is not set. Call initialize() first.')
129129

130-
path = self._resolve_path(path)
131-
return await asyncio.to_thread(self._sync_read, path)
130+
resolved = self._resolve_path(path)
131+
return await asyncio.to_thread(self._sync_read, resolved)
132132

133133
@override
134-
async def write_file(self, path: str, content: str | bytes) -> None:
134+
async def write_file(self, path: str | Path, content: str | bytes) -> None:
135135
if self._working_dir is None:
136136
raise RuntimeError('`working_dir` is not set. Call initialize() first.')
137137

138-
path = self._resolve_path(path)
139-
return await asyncio.to_thread(self._sync_write, path, content)
138+
resolved = self._resolve_path(path)
139+
return await asyncio.to_thread(self._sync_write, resolved, content)
140140

141-
def _resolve_path(self, path: str) -> str:
141+
def _resolve_path(self, path: str | Path) -> str:
142142
"""Resolve a relative path against the working directory."""
143+
path = str(path)
143144
if os.path.isabs(path):
144145
return path
145146
return os.path.join(self._working_dir, path)

src/google/adk/examples/example_util.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
_FUNCTION_RESPONSE_SUFFIX = "\n```\n"
4747

4848

49-
# TODO(yaojie): Add unit tests for this function.
5049
def convert_examples_to_text(
5150
examples: list[Example], model: Optional[str]
5251
) -> str:

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,11 @@ async def _resolve_toolset_auth(
143143
if not auth_config:
144144
continue
145145

146+
auth_config_copy = auth_config.model_copy(deep=True)
146147
try:
147-
credential = await CredentialManager(auth_config).get_auth_credential(
148-
callback_context
149-
)
148+
credential = await CredentialManager(
149+
auth_config_copy
150+
).get_auth_credential(callback_context)
150151
except ValueError as e:
151152
# Validation errors from CredentialManager should be logged but not
152153
# block the flow - the toolset may still work without auth
@@ -158,14 +159,16 @@ async def _resolve_toolset_auth(
158159
credential = None
159160

160161
if credential:
161-
# Populate in-place for toolset to use in get_tools()
162-
auth_config.exchanged_auth_credential = credential
162+
# Store in invocation context to avoid data leakage and race conditions
163+
invocation_context.credential_by_key[auth_config.credential_key] = (
164+
credential
165+
)
163166
else:
164167
# Need auth - will interrupt
165168
toolset_id = (
166169
f'{TOOLSET_AUTH_CREDENTIAL_ID_PREFIX}{type(tool_union).__name__}'
167170
)
168-
pending_auth_requests[toolset_id] = auth_config
171+
pending_auth_requests[toolset_id] = auth_config_copy
169172

170173
if not pending_auth_requests:
171174
return

0 commit comments

Comments
 (0)