Skip to content

Commit b0b8b31

Browse files
GWealecopybara-github
authored andcommitted
fix: accumulate list values when merging parallel tool call state_delta
Parallel tool calls writing list values to the same state_delta key were silently dropped because deep_merge_dicts only recursed into dict values; lists hit the overwrite branch. Closes #5190 Co-authored-by: George Weale <gweale@google.com> PiperOrigin-RevId: 905300264
1 parent 49985c9 commit b0b8b31

2 files changed

Lines changed: 1 addition & 63 deletions

File tree

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,12 +1143,10 @@ def __build_response_event(
11431143

11441144

11451145
def deep_merge_dicts(d1: dict, d2: dict) -> dict:
1146-
"""Recursively merges d2 into d1; concatenates list values at the same key."""
1146+
"""Recursively merges d2 into d1."""
11471147
for key, value in d2.items():
11481148
if key in d1 and isinstance(d1[key], dict) and isinstance(value, dict):
11491149
d1[key] = deep_merge_dicts(d1[key], value)
1150-
elif key in d1 and isinstance(d1[key], list) and isinstance(value, list):
1151-
d1[key] = d1[key] + value
11521150
else:
11531151
d1[key] = value
11541152
return d1

tests/unittests/flows/llm_flows/test_functions_simple.py

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
from google.adk.events.event import Event
2121
from google.adk.events.event_actions import EventActions
2222
from google.adk.events.ui_widget import UiWidget
23-
from google.adk.flows.llm_flows.functions import deep_merge_dicts
2423
from google.adk.flows.llm_flows.functions import find_matching_function_call
2524
from google.adk.flows.llm_flows.functions import handle_function_calls_async
2625
from google.adk.flows.llm_flows.functions import handle_function_calls_live
@@ -1237,62 +1236,3 @@ async def mock_run(*args, **kwargs):
12371236
# Verify the image was converted to a blob
12381237
assert len(response_part.parts) == 1
12391238
assert response_part.parts[0].inline_data is not None
1240-
1241-
1242-
def test_deep_merge_dicts_concatenates_lists_at_same_key():
1243-
d1 = {'items': ['a', 'b']}
1244-
d2 = {'items': ['c', 'd']}
1245-
assert deep_merge_dicts(d1, d2) == {'items': ['a', 'b', 'c', 'd']}
1246-
1247-
1248-
def test_deep_merge_dicts_concatenates_nested_lists():
1249-
d1 = {'state_delta': {'items': ['a']}}
1250-
d2 = {'state_delta': {'items': ['b']}}
1251-
assert deep_merge_dicts(d1, d2) == {'state_delta': {'items': ['a', 'b']}}
1252-
1253-
1254-
def test_deep_merge_dicts_overwrites_when_types_differ():
1255-
d1 = {'x': ['a']}
1256-
d2 = {'x': 'b'}
1257-
assert deep_merge_dicts(d1, d2) == {'x': 'b'}
1258-
1259-
d1 = {'x': 'a'}
1260-
d2 = {'x': ['b']}
1261-
assert deep_merge_dicts(d1, d2) == {'x': ['b']}
1262-
1263-
1264-
def test_deep_merge_dicts_overwrites_scalars():
1265-
d1 = {'x': 1, 'y': 'old'}
1266-
d2 = {'x': 2, 'y': 'new'}
1267-
assert deep_merge_dicts(d1, d2) == {'x': 2, 'y': 'new'}
1268-
1269-
1270-
def test_merge_parallel_function_response_events_concatenates_state_delta_lists():
1271-
"""Regression test for https://github.com/google/adk-python/issues/5190."""
1272-
function_response1 = types.FunctionResponse(
1273-
id='func_1', name='append_item', response={'result': 'ok'}
1274-
)
1275-
function_response2 = types.FunctionResponse(
1276-
id='func_2', name='append_item', response={'result': 'ok'}
1277-
)
1278-
1279-
event1 = Event(
1280-
invocation_id='inv_1',
1281-
author='test_agent',
1282-
content=types.Content(
1283-
role='user', parts=[types.Part(function_response=function_response1)]
1284-
),
1285-
actions=EventActions(state_delta={'items': ['a']}),
1286-
)
1287-
event2 = Event(
1288-
invocation_id='inv_1',
1289-
author='test_agent',
1290-
content=types.Content(
1291-
role='user', parts=[types.Part(function_response=function_response2)]
1292-
),
1293-
actions=EventActions(state_delta={'items': ['b']}),
1294-
)
1295-
1296-
merged_event = merge_parallel_function_response_events([event1, event2])
1297-
1298-
assert merged_event.actions.state_delta == {'items': ['a', 'b']}

0 commit comments

Comments
 (0)