@@ -1860,6 +1860,59 @@ async def test_content_to_message_param_assistant_message():
18601860 assert message ["content" ] == "Test response"
18611861
18621862
1863+ @pytest .mark .asyncio
1864+ async def test_content_to_message_param_user_filters_thought_parts ():
1865+ thought_part = types .Part .from_text (text = "internal reasoning" )
1866+ thought_part .thought = True
1867+ content_part = types .Part .from_text (text = "visible content" )
1868+ content = types .Content (role = "user" , parts = [thought_part , content_part ])
1869+
1870+ message = await _content_to_message_param (content )
1871+
1872+ assert message ["role" ] == "user"
1873+ assert message ["content" ] == "visible content"
1874+
1875+
1876+ @pytest .mark .asyncio
1877+ async def test_content_to_message_param_assistant_thought_message ():
1878+ part = types .Part .from_text (text = "internal reasoning" )
1879+ part .thought = True
1880+ content = types .Content (role = "assistant" , parts = [part ])
1881+
1882+ message = await _content_to_message_param (content )
1883+
1884+ assert message ["role" ] == "assistant"
1885+ assert message ["content" ] is None
1886+ assert message ["reasoning_content" ] == "internal reasoning"
1887+
1888+
1889+ @pytest .mark .asyncio
1890+ async def test_content_to_message_param_model_thought_message ():
1891+ part = types .Part .from_text (text = "internal reasoning" )
1892+ part .thought = True
1893+ content = types .Content (role = "model" , parts = [part ])
1894+
1895+ message = await _content_to_message_param (content )
1896+
1897+ assert message ["role" ] == "assistant"
1898+ assert message ["content" ] is None
1899+ assert message ["reasoning_content" ] == "internal reasoning"
1900+
1901+
1902+ @pytest .mark .asyncio
1903+ async def test_content_to_message_param_assistant_thought_and_content_message ():
1904+ thought_part = types .Part .from_text (text = "internal reasoning" )
1905+ thought_part .thought = True
1906+ content_part = types .Part .from_text (text = "visible content" )
1907+ content = types .Content (role = "assistant" , parts = [thought_part , content_part ])
1908+
1909+ message = await _content_to_message_param (content )
1910+
1911+ assert message ["role" ] == "assistant"
1912+ assert message ["content" ] == "visible content"
1913+ assert message ["reasoning_content" ] == "internal reasoning"
1914+
1915+
18631916@pytest .mark .asyncio
18641917async def test_content_to_message_param_function_call ():
18651918 content = types .Content (
@@ -2087,42 +2140,35 @@ def test_split_message_content_prefers_existing_structured_calls():
20872140
20882141
20892142@pytest .mark .asyncio
2090- async def test_get_content_filters_thought_parts ():
2091- """Test that thought parts are filtered from content.
2092-
2093- Thought parts contain model reasoning that should not be sent back to
2094- the model in subsequent turns. This test verifies that _get_content
2095- skips parts with thought=True.
2143+ async def test_get_content_does_not_filter_thought_parts ():
2144+ """Test that _get_content does not drop thought parts.
20962145
2097- See: https://github.com/google/adk-python/issues/3948
2146+ Thought filtering is handled by the caller (e.g., _content_to_message_param)
2147+ to avoid duplicating logic across helpers.
20982148 """
2099- # Create a thought part (reasoning) and a regular text part
21002149 thought_part = types .Part (text = "Internal reasoning..." , thought = True )
21012150 regular_part = types .Part .from_text (text = "Visible response" )
2102- parts = [thought_part , regular_part ]
21032151
2104- content = await _get_content (parts )
2152+ content = await _get_content ([ thought_part , regular_part ] )
21052153
2106- # The thought part should be filtered out, leaving only the regular text
2107- assert content == "Visible response"
2154+ assert content == [
2155+ {"type" : "text" , "text" : "Internal reasoning..." },
2156+ {"type" : "text" , "text" : "Visible response" },
2157+ ]
21082158
21092159
21102160@pytest .mark .asyncio
2111- async def test_get_content_filters_all_thought_parts ():
2112- """Test that all thought parts are filtered when only thoughts present.
2113-
2114- When all parts are thought parts, _get_content should return an empty list.
2115-
2116- See: https://github.com/google/adk-python/issues/3948
2117- """
2161+ async def test_get_content_all_thought_parts ():
2162+ """Test that thought parts convert like regular text parts."""
21182163 thought_part1 = types .Part (text = "First reasoning..." , thought = True )
21192164 thought_part2 = types .Part (text = "Second reasoning..." , thought = True )
2120- parts = [thought_part1 , thought_part2 ]
21212165
2122- content = await _get_content (parts )
2166+ content = await _get_content ([ thought_part1 , thought_part2 ] )
21232167
2124- # All thought parts should be filtered out
2125- assert content == []
2168+ assert content == [
2169+ {"type" : "text" , "text" : "First reasoning..." },
2170+ {"type" : "text" , "text" : "Second reasoning..." },
2171+ ]
21262172
21272173
21282174@pytest .mark .asyncio
0 commit comments