@@ -7,6 +7,7 @@ use termimad::MadSkin;
77#[ derive( Clone ) ]
88pub struct Output {
99 skin : MadSkin ,
10+ reasoning_skin : MadSkin ,
1011 writer : Option < SharedWriter > ,
1112}
1213
@@ -28,19 +29,43 @@ impl Output {
2829 skin. code_block . set_fg ( termimad:: ansi ( 15 ) ) ; // bright white text
2930 // If a global SharedWriter is available (when chat has initialized
3031 // the readline UI), use it to avoid cursor glitches
32+ let mut reasoning_skin = MadSkin :: default ( ) ;
33+ // Keep it simple for copy-paste friendliness
34+ reasoning_skin. set_headers_fg ( termimad:: ansi ( 5 ) ) ; // purple
35+ reasoning_skin. bold . set_fg ( termimad:: ansi ( 7 ) ) ; // light grey
36+
37+ // Make inline code stand out with color but no background
38+ reasoning_skin. inline_code . set_fg ( termimad:: ansi ( 11 ) ) ; // bright yellow
39+ reasoning_skin
40+ . inline_code
41+ . set_bg ( termimad:: crossterm:: style:: Color :: Black ) ;
42+
43+ // Fix code blocks to not have background
44+ reasoning_skin
45+ . code_block
46+ . set_bg ( termimad:: crossterm:: style:: Color :: Black ) ;
47+ reasoning_skin. code_block . set_fg ( termimad:: ansi ( 7 ) ) ; // bright white
48+ // If a global SharedWriter is available (when chat has initialized
49+ // the readline UI), use it to avoid cursor glitches
3150 if let Some ( shared) = crate :: tracing_writer:: get_shared_writer ( ) {
3251 Self {
3352 skin,
53+ reasoning_skin,
3454 writer : Some ( shared) ,
3555 }
3656 } else {
37- Self { skin, writer : None }
57+ Self {
58+ skin,
59+ reasoning_skin,
60+ writer : None ,
61+ }
3862 }
3963 }
4064
4165 pub fn with_writer ( self , writer : SharedWriter ) -> Self {
4266 Self {
4367 skin : self . skin ,
68+ reasoning_skin : self . reasoning_skin ,
4469 writer : Some ( writer) ,
4570 }
4671 }
@@ -63,16 +88,40 @@ impl Output {
6388 }
6489 }
6590
91+ /// flush the buffer
92+ fn flush ( & self ) {
93+ if let Some ( ref writer) = self . writer {
94+ // Clone the writer to get a mutable version
95+ let mut writer = writer. clone ( ) ;
96+ let _ = writer. flush ( ) ;
97+ } else {
98+ use std:: io:: { self , Write } ;
99+ let _ = io:: stdout ( ) . flush ( ) ;
100+ }
101+ }
102+
103+ /// Helper method to write output either to SharedWriter or stdout
104+ fn write_line_noclear ( & self , content : & str ) {
105+ if let Some ( ref writer) = self . writer {
106+ // Clone the writer to get a mutable version
107+ let mut writer = writer. clone ( ) ;
108+ // When using SharedWriter, it handles the synchronization
109+ let _ = writeln ! ( writer, "{}" , content) ;
110+ } else {
111+ // Fallback to regular println
112+ println ! ( "{}" , content) ;
113+ }
114+ }
115+
66116 /// Print an agent message with markdown formatting
67117 pub fn agent_message ( & self , agent_name : & str , content : & str ) {
68118 // Clear visual separation without box drawing chars
69- self . write_line ( "" ) ;
70- self . write_line ( & format ! (
119+ self . write_line_noclear ( "" ) ;
120+ self . write_line_noclear ( & format ! (
71121 "{} {}" ,
72122 agent_name. bright_cyan( ) . bold( ) ,
73123 "says:" . dimmed( )
74124 ) ) ;
75- self . write_line ( "" ) ;
76125
77126 // Use termimad to format the markdown content
78127 use termimad:: FmtText ;
@@ -81,7 +130,27 @@ impl Output {
81130
82131 // Write each line through our write_line method
83132 for line in formatted_string. lines ( ) {
84- self . write_line ( line) ;
133+ self . write_line_noclear ( line) ;
134+ }
135+
136+ self . write_line ( "" ) ;
137+ }
138+
139+ /// Print an agent message with markdown formatting
140+ pub fn agent_reasoning ( & self , agent_name : & str , content : & str ) {
141+ self . write_line_noclear ( & format ! (
142+ "{} reasoning:" ,
143+ agent_name. bright_magenta( ) . bold( )
144+ ) ) ;
145+
146+ // Use termimad to format the markdown content
147+ use termimad:: FmtText ;
148+ let formatted = FmtText :: from ( & self . reasoning_skin , content, Some ( 80 ) ) ;
149+ let formatted_string = formatted. to_string ( ) ;
150+
151+ // Write each line through our write_line method
152+ for line in formatted_string. lines ( ) {
153+ self . write_line_noclear ( line) ;
85154 }
86155
87156 self . write_line ( "" ) ;
@@ -126,7 +195,7 @@ impl Output {
126195
127196 /// Print a tool call
128197 pub fn tool_call ( & self , tool_name : & str , args : & str ) {
129- self . write_line ( & format ! (
198+ self . write_line_noclear ( & format ! (
130199 " {} Using tool: {}" ,
131200 ">>" . bright_blue( ) ,
132201 tool_name. bright_yellow( )
@@ -135,30 +204,32 @@ impl Output {
135204 // Indent each line of the args for proper alignment
136205 for ( i, line) in args. lines ( ) . enumerate ( ) {
137206 if i == 0 {
138- self . write_line ( & format ! ( " Args: {}" , line) . dimmed ( ) . to_string ( ) ) ;
207+ self . write_line_noclear ( & format ! ( " Args: {}" , line) . dimmed ( ) . to_string ( ) ) ;
139208 } else {
140- self . write_line ( & format ! ( " {}" , line) . dimmed ( ) . to_string ( ) ) ;
209+ self . write_line_noclear ( & format ! ( " {}" , line) . dimmed ( ) . to_string ( ) ) ;
141210 }
142211 }
143212 }
213+ self . flush ( ) ;
144214 }
145215
146216 /// Print a tool result
147217 pub fn tool_result ( & self , result : & str ) {
148218 // Handle multi-line results with proper indentation
149219 let lines: Vec < & str > = result. lines ( ) . collect ( ) ;
150220 if lines. len ( ) == 1 {
151- self . write_line ( & format ! (
221+ self . write_line_noclear ( & format ! (
152222 " {} Tool result: {}" ,
153223 "=>" . bright_green( ) ,
154224 result. dimmed( )
155225 ) ) ;
156226 } else {
157- self . write_line ( & format ! ( " {} Tool result:" , "=>" . bright_green( ) ) ) ;
227+ self . write_line_noclear ( & format ! ( " {} Tool result:" , "=>" . bright_green( ) ) ) ;
158228 for line in lines {
159- self . write_line ( & format ! ( " {}" , line. dimmed( ) ) ) ;
229+ self . write_line_noclear ( & format ! ( " {}" , line. dimmed( ) ) ) ;
160230 }
161231 }
232+ self . flush ( ) ;
162233 }
163234
164235 /// Print a "working on it" status message
@@ -196,15 +267,16 @@ impl Output {
196267
197268 // Write each line through our write_line method
198269 for line in formatted_string. lines ( ) {
199- self . write_line ( line) ;
270+ self . write_line_noclear ( line) ;
200271 }
272+ self . flush ( ) ;
201273 }
202274
203275 /// Print a table-like header
204276 #[ allow( dead_code) ]
205277 pub fn table_header ( & self , columns : & [ & str ] ) {
206278 let header = columns. join ( " | " ) ;
207- self . write_line ( & format ! ( " {}" , header. bright_white( ) . bold( ) ) ) ;
279+ self . write_line_noclear ( & format ! ( " {}" , header. bright_white( ) . bold( ) ) ) ;
208280 self . write_line ( & format ! ( " {}" , "─" . repeat( header. len( ) ) . dimmed( ) ) ) ;
209281 }
210282
0 commit comments