Skip to content

Commit 773ddfc

Browse files
ronmrdechaiRon Mordechai
andauthored
feat: add tool_use_result field to UserMessage (#495)
## Summary Having tool_use_result on UserMessage allows for rich formatting of Claude's built-in tools in programs that use the SDK. Would love to gain access to this. Co-authored-by: Ron Mordechai <ronmrdechai@fb.com>
1 parent bfd2869 commit 773ddfc

3 files changed

Lines changed: 70 additions & 0 deletions

File tree

src/claude_agent_sdk/_internal/message_parser.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ def parse_message(data: dict[str, Any]) -> Message:
4848
case "user":
4949
try:
5050
parent_tool_use_id = data.get("parent_tool_use_id")
51+
tool_use_result = data.get("tool_use_result")
5152
uuid = data.get("uuid")
5253
if isinstance(data["message"]["content"], list):
5354
user_content_blocks: list[ContentBlock] = []
@@ -77,11 +78,13 @@ def parse_message(data: dict[str, Any]) -> Message:
7778
content=user_content_blocks,
7879
uuid=uuid,
7980
parent_tool_use_id=parent_tool_use_id,
81+
tool_use_result=tool_use_result,
8082
)
8183
return UserMessage(
8284
content=data["message"]["content"],
8385
uuid=uuid,
8486
parent_tool_use_id=parent_tool_use_id,
87+
tool_use_result=tool_use_result,
8588
)
8689
except KeyError as e:
8790
raise MessageParseError(

src/claude_agent_sdk/types.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,7 @@ class UserMessage:
564564
content: str | list[ContentBlock]
565565
uuid: str | None = None
566566
parent_tool_use_id: str | None = None
567+
tool_use_result: dict[str, Any] | None = None
567568

568569

569570
@dataclass

tests/test_message_parser.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,72 @@ def test_parse_user_message_inside_subagent(self):
156156
assert isinstance(message, UserMessage)
157157
assert message.parent_tool_use_id == "toolu_01Xrwd5Y13sEHtzScxR77So8"
158158

159+
def test_parse_user_message_with_tool_use_result(self):
160+
"""Test parsing a user message with tool_use_result field.
161+
162+
The tool_use_result field contains metadata about tool execution results,
163+
including file edit details like oldString, newString, and structuredPatch.
164+
"""
165+
tool_result_data = {
166+
"filePath": "/path/to/file.py",
167+
"oldString": "old code",
168+
"newString": "new code",
169+
"originalFile": "full file contents",
170+
"structuredPatch": [
171+
{
172+
"oldStart": 33,
173+
"oldLines": 7,
174+
"newStart": 33,
175+
"newLines": 7,
176+
"lines": [
177+
" # comment",
178+
"- old line",
179+
"+ new line",
180+
],
181+
}
182+
],
183+
"userModified": False,
184+
"replaceAll": False,
185+
}
186+
data = {
187+
"type": "user",
188+
"message": {
189+
"role": "user",
190+
"content": [
191+
{
192+
"tool_use_id": "toolu_vrtx_01KXWexk3NJdwkjWzPMGQ2F1",
193+
"type": "tool_result",
194+
"content": "The file has been updated.",
195+
}
196+
],
197+
},
198+
"parent_tool_use_id": None,
199+
"session_id": "84afb479-17ae-49af-8f2b-666ac2530c3a",
200+
"uuid": "2ace3375-1879-48a0-a421-6bce25a9295a",
201+
"tool_use_result": tool_result_data,
202+
}
203+
message = parse_message(data)
204+
assert isinstance(message, UserMessage)
205+
assert message.tool_use_result == tool_result_data
206+
assert message.tool_use_result["filePath"] == "/path/to/file.py"
207+
assert message.tool_use_result["oldString"] == "old code"
208+
assert message.tool_use_result["newString"] == "new code"
209+
assert message.tool_use_result["structuredPatch"][0]["oldStart"] == 33
210+
assert message.uuid == "2ace3375-1879-48a0-a421-6bce25a9295a"
211+
212+
def test_parse_user_message_with_string_content_and_tool_use_result(self):
213+
"""Test parsing a user message with string content and tool_use_result."""
214+
tool_result_data = {"filePath": "/path/to/file.py", "userModified": True}
215+
data = {
216+
"type": "user",
217+
"message": {"content": "Simple string content"},
218+
"tool_use_result": tool_result_data,
219+
}
220+
message = parse_message(data)
221+
assert isinstance(message, UserMessage)
222+
assert message.content == "Simple string content"
223+
assert message.tool_use_result == tool_result_data
224+
159225
def test_parse_valid_assistant_message(self):
160226
"""Test parsing a valid assistant message."""
161227
data = {

0 commit comments

Comments
 (0)