@@ -108,6 +108,27 @@ def test_validate_tool_use_result_messages_raises_when_tool_result_mixed_with_ot
108108 validate_tool_use_result_messages (messages )
109109
110110
111+ def test_validate_tool_use_result_messages_raises_for_earlier_mixed_tool_result () -> None :
112+ """Raises when an earlier message mixes tool_result with other content."""
113+ messages = [
114+ SamplingMessage (
115+ role = "assistant" ,
116+ content = ToolUseContent (type = "tool_use" , id = "tool-1" , name = "test" , input = {}),
117+ ),
118+ SamplingMessage (
119+ role = "user" ,
120+ content = [
121+ ToolResultContent (type = "tool_result" , tool_use_id = "tool-1" ),
122+ TextContent (type = "text" , text = "also this" ),
123+ ],
124+ ),
125+ SamplingMessage (role = "assistant" , content = TextContent (type = "text" , text = "done" )),
126+ ]
127+
128+ with pytest .raises (ValueError , match = "only tool_result content" ):
129+ validate_tool_use_result_messages (messages )
130+
131+
111132def test_validate_tool_use_result_messages_raises_when_tool_result_without_previous_tool_use () -> None :
112133 """Raises when tool_result appears without preceding tool_use."""
113134 messages = [
@@ -136,6 +157,39 @@ def test_validate_tool_use_result_messages_raises_when_tool_result_ids_dont_matc
136157 validate_tool_use_result_messages (messages )
137158
138159
160+ def test_validate_tool_use_result_messages_raises_when_earlier_tool_result_ids_dont_match_tool_use () -> None :
161+ """Raises when an earlier tool_result does not match the previous tool_use."""
162+ messages = [
163+ SamplingMessage (
164+ role = "assistant" ,
165+ content = ToolUseContent (type = "tool_use" , id = "tool-1" , name = "test" , input = {}),
166+ ),
167+ SamplingMessage (
168+ role = "user" ,
169+ content = ToolResultContent (type = "tool_result" , tool_use_id = "tool-2" ),
170+ ),
171+ SamplingMessage (role = "assistant" , content = TextContent (type = "text" , text = "done" )),
172+ ]
173+
174+ with pytest .raises (ValueError , match = "do not match" ):
175+ validate_tool_use_result_messages (messages )
176+
177+
178+ def test_validate_tool_use_result_messages_raises_when_tool_use_is_not_answered () -> None :
179+ """Raises when a tool_use is followed by a non-tool_result message."""
180+ messages = [
181+ SamplingMessage (
182+ role = "assistant" ,
183+ content = ToolUseContent (type = "tool_use" , id = "tool-1" , name = "test" , input = {}),
184+ ),
185+ SamplingMessage (role = "user" , content = TextContent (type = "text" , text = "not a result" )),
186+ SamplingMessage (role = "assistant" , content = TextContent (type = "text" , text = "done" )),
187+ ]
188+
189+ with pytest .raises (ValueError , match = "do not match" ):
190+ validate_tool_use_result_messages (messages )
191+
192+
139193def test_validate_tool_use_result_messages_no_error_when_tool_result_matches_tool_use () -> None :
140194 """No error when tool_result IDs match tool_use IDs."""
141195 messages = [
@@ -149,3 +203,34 @@ def test_validate_tool_use_result_messages_no_error_when_tool_result_matches_too
149203 ),
150204 ]
151205 validate_tool_use_result_messages (messages ) # Should not raise
206+
207+
208+ def test_validate_tool_use_result_messages_no_error_for_multiple_tool_pairs () -> None :
209+ """No error when every tool_use in the history has a matching tool_result."""
210+ messages = [
211+ SamplingMessage (role = "user" , content = TextContent (type = "text" , text = "first" )),
212+ SamplingMessage (
213+ role = "assistant" ,
214+ content = ToolUseContent (type = "tool_use" , id = "tool-1" , name = "test" , input = {}),
215+ ),
216+ SamplingMessage (
217+ role = "user" ,
218+ content = ToolResultContent (type = "tool_result" , tool_use_id = "tool-1" ),
219+ ),
220+ SamplingMessage (
221+ role = "assistant" ,
222+ content = [
223+ ToolUseContent (type = "tool_use" , id = "tool-2" , name = "test" , input = {}),
224+ ToolUseContent (type = "tool_use" , id = "tool-3" , name = "test" , input = {}),
225+ ],
226+ ),
227+ SamplingMessage (
228+ role = "user" ,
229+ content = [
230+ ToolResultContent (type = "tool_result" , tool_use_id = "tool-3" ),
231+ ToolResultContent (type = "tool_result" , tool_use_id = "tool-2" ),
232+ ],
233+ ),
234+ ]
235+
236+ validate_tool_use_result_messages (messages )
0 commit comments