Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions python/packages/core/agent_framework/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,16 @@ def _parse_content_list(contents_data: Sequence[Any]) -> list[Content]:
"""Parse a list of content data into appropriate Content objects.

Args:
contents_data: List of content data (strings, dicts, or already constructed objects)
contents_data: List of content data (strings, dicts, or already constructed objects).
A single string is treated as one text item.

Returns:
List of Content objects with unknown types logged and ignored
"""
if isinstance(contents_data, str):
# A string is itself a sequence of strings, so iterating it would create one text
# content per character.
contents_data = [contents_data]
contents: list[Content] = []
for content_data in contents_data:
if content_data is None:
Expand Down Expand Up @@ -2072,7 +2077,8 @@ def __init__(
Args:
role: The role of the author of the message (e.g., "user", "assistant", "system", "tool").
contents: A sequence of content items. Can be Content objects, strings (auto-converted
to TextContent), or dicts (parsed via Content.from_dict). Defaults to empty list.
to TextContent), or dicts (parsed via Content.from_dict). A single string is
treated as one text item. Defaults to empty list.

Keyword Args:
author_name: Optional name of the author of the message.
Expand Down
28 changes: 28 additions & 0 deletions python/packages/core/tests/core/test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -1167,6 +1167,25 @@ def test_chat_message_text():
assert isinstance(message.contents[0], Content)


@pytest.mark.parametrize(
"message",
[Message("user", "Hello, how are you?"), Message(role="user", contents="Hello, how are you?")],
ids=["positional", "keyword"],
)
def test_chat_message_with_single_string_contents(message: Message) -> None:
"""A bare string is one text content, not a sequence of single-character contents."""
assert len(message.contents) == 1
assert message.contents[0].type == "text"
assert message.text == "Hello, how are you?"


def test_chat_message_with_empty_string_contents() -> None:
message = Message("user", "")

assert len(message.contents) == 1
assert message.text == ""


def test_chat_message_contents():
"""Test the Message class to ensure it initializes correctly with contents."""
# Create a Message with a role and multiple contents
Expand Down Expand Up @@ -4553,6 +4572,15 @@ def test_parse_content_list_with_dicts():
assert result[0].text == "hello"


def test_parse_content_list_with_single_string():
"""Test _parse_content_list treats a bare string as one text item, not one per character."""
result = _parse_content_list("hello")

assert len(result) == 1
assert result[0].type == "text"
assert result[0].text == "hello"


def test_parse_content_list_with_mixed_content_and_dict():
"""Test _parse_content_list handles a mix of Content objects and dicts."""
content = Content(type="text", text="hello")
Expand Down
Loading