@@ -241,6 +241,43 @@ def test_reasoning_collapsed_marker_shows_even_without_answer(self):
241241 self .assertIn ("💭 ..." , out )
242242 self .assertNotIn ("pensive thoughts" , out )
243243
244+ def test_reasoning_marker_before_tool_call_label (self ):
245+ """For a reasoned tool call the marker comes first: reasoning
246+ happened before the tool invocation, so it renders above the
247+ tool label."""
248+ tui , buf = make_tui ()
249+ tui .session .last_messages = [
250+ Message (role = "user" , content = "read the file" ),
251+ Message (
252+ role = "assistant" , content = "let me check the path first" ,
253+ reasoning = "let me check the path first" ,
254+ tool_calls = [ToolCall (id = "1" , name = "Read" , arguments = "{}" )],
255+ ),
256+ Message (role = "tool" , content = "file contents" , tool_call_id = "1" , name = "Read" ),
257+ ]
258+ tui .console .print (tui ._render_conversation ())
259+ out = buf .getvalue ()
260+ self .assertIn ("💭 ..." , out )
261+ self .assertIn ("🤖 Read" , out )
262+ self .assertLess (out .index ("💭 ..." ), out .index ("🤖 Read" ))
263+ self .assertNotIn ("let me check" , out )
264+
265+ def test_non_string_reasoning_does_not_crash (self ):
266+ """A malformed (non-string) reasoning value must not raise —
267+ display falls back to the raw content."""
268+ tui , buf = make_tui ()
269+ tui .session .last_messages = [
270+ Message (role = "user" , content = "go" ),
271+ Message (
272+ role = "assistant" , content = "full text here" ,
273+ reasoning = ["not" , "a" , "string" ],
274+ ),
275+ ]
276+ tui .console .print (tui ._render_conversation ())
277+ out = buf .getvalue ()
278+ self .assertIn ("full text here" , out )
279+ self .assertNotIn ("💭 ..." , out )
280+
244281 def test_strip_reasoning (self ):
245282 """_strip_reasoning removes the leading reasoning prefix and
246283 leaves non-matching text untouched."""
0 commit comments