Skip to content

Commit e141980

Browse files
committed
fix: preserve empty-string text parts in A2A converter
Part(text='') is valid — it is produced by code_execution_utils.py when code execution returns None, and by interactions_utils.py when the Interactions API returns None text. Gemini 2.5 Flash thinking mode also emits empty text parts. The truthiness check `if part.text:` treats '' as falsy, causing the converter to skip the part entirely. When all parts in a response are empty the A2A message ends up with zero parts and the client sees "broken thinking" with no content. Change the check to `if part.text is not None:` so that empty strings are correctly wrapped as TextPart while None is still skipped. Add a regression test for the empty-string case. Fixes #5341
1 parent 60b9073 commit e141980

2 files changed

Lines changed: 18 additions & 1 deletion

File tree

src/google/adk/a2a/converters/part_converter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ def convert_genai_part_to_a2a_part(
179179
) -> Optional[a2a_types.Part]:
180180
"""Convert a Google GenAI Part to an A2A Part."""
181181

182-
if part.text:
182+
if part.text is not None:
183183
a2a_part = a2a_types.TextPart(text=part.text)
184184
if part.thought is not None:
185185
a2a_part.metadata = {_get_adk_metadata_key('thought'): part.thought}

tests/unittests/a2a/converters/test_part_converter.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,23 @@ def test_convert_text_part_with_thought(self):
297297
assert result.root.metadata is not None
298298
assert result.root.metadata[_get_adk_metadata_key("thought")]
299299

300+
def test_convert_empty_text_part(self):
301+
"""Test that Part(text='') is preserved, not dropped.
302+
303+
Regression test for #5341: empty-string text parts are valid and
304+
must not fall through to the unsupported-part warning.
305+
"""
306+
# Arrange
307+
genai_part = genai_types.Part(text="")
308+
309+
# Act
310+
result = convert_genai_part_to_a2a_part(genai_part)
311+
312+
# Assert — should produce a valid TextPart, not None
313+
assert result is not None
314+
assert isinstance(result.root, a2a_types.TextPart)
315+
assert result.root.text == ""
316+
300317
def test_convert_file_data_part(self):
301318
"""Test conversion of GenAI file_data Part to A2A Part."""
302319
# Arrange

0 commit comments

Comments
 (0)