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
3 changes: 3 additions & 0 deletions src/claude_agent_sdk/_internal/message_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def parse_message(data: dict[str, Any]) -> Message:
case "user":
try:
parent_tool_use_id = data.get("parent_tool_use_id")
tool_use_result = data.get("tool_use_result")
uuid = data.get("uuid")
if isinstance(data["message"]["content"], list):
user_content_blocks: list[ContentBlock] = []
Expand Down Expand Up @@ -77,11 +78,13 @@ def parse_message(data: dict[str, Any]) -> Message:
content=user_content_blocks,
uuid=uuid,
parent_tool_use_id=parent_tool_use_id,
tool_use_result=tool_use_result,
)
return UserMessage(
content=data["message"]["content"],
uuid=uuid,
parent_tool_use_id=parent_tool_use_id,
tool_use_result=tool_use_result,
)
except KeyError as e:
raise MessageParseError(
Expand Down
1 change: 1 addition & 0 deletions src/claude_agent_sdk/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,7 @@ class UserMessage:
content: str | list[ContentBlock]
uuid: str | None = None
parent_tool_use_id: str | None = None
tool_use_result: dict[str, Any] | None = None


@dataclass
Expand Down
66 changes: 66 additions & 0 deletions tests/test_message_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,72 @@ def test_parse_user_message_inside_subagent(self):
assert isinstance(message, UserMessage)
assert message.parent_tool_use_id == "toolu_01Xrwd5Y13sEHtzScxR77So8"

def test_parse_user_message_with_tool_use_result(self):
"""Test parsing a user message with tool_use_result field.
The tool_use_result field contains metadata about tool execution results,
including file edit details like oldString, newString, and structuredPatch.
"""
tool_result_data = {
"filePath": "/path/to/file.py",
"oldString": "old code",
"newString": "new code",
"originalFile": "full file contents",
"structuredPatch": [
{
"oldStart": 33,
"oldLines": 7,
"newStart": 33,
"newLines": 7,
"lines": [
" # comment",
"- old line",
"+ new line",
],
}
],
"userModified": False,
"replaceAll": False,
}
data = {
"type": "user",
"message": {
"role": "user",
"content": [
{
"tool_use_id": "toolu_vrtx_01KXWexk3NJdwkjWzPMGQ2F1",
"type": "tool_result",
"content": "The file has been updated.",
}
],
},
"parent_tool_use_id": None,
"session_id": "84afb479-17ae-49af-8f2b-666ac2530c3a",
"uuid": "2ace3375-1879-48a0-a421-6bce25a9295a",
"tool_use_result": tool_result_data,
}
message = parse_message(data)
assert isinstance(message, UserMessage)
assert message.tool_use_result == tool_result_data
assert message.tool_use_result["filePath"] == "/path/to/file.py"
assert message.tool_use_result["oldString"] == "old code"
assert message.tool_use_result["newString"] == "new code"
assert message.tool_use_result["structuredPatch"][0]["oldStart"] == 33
assert message.uuid == "2ace3375-1879-48a0-a421-6bce25a9295a"

def test_parse_user_message_with_string_content_and_tool_use_result(self):
"""Test parsing a user message with string content and tool_use_result."""
tool_result_data = {"filePath": "/path/to/file.py", "userModified": True}
data = {
"type": "user",
"message": {"content": "Simple string content"},
"tool_use_result": tool_result_data,
}
message = parse_message(data)
assert isinstance(message, UserMessage)
assert message.content == "Simple string content"
assert message.tool_use_result == tool_result_data

def test_parse_valid_assistant_message(self):
"""Test parsing a valid assistant message."""
data = {
Expand Down