From 54e2a66b7d60108874104797e5840f4e484748e6 Mon Sep 17 00:00:00 2001 From: Dhanji Prasanna Date: Fri, 3 Oct 2025 14:04:17 +1000 Subject: [PATCH] fixed newline character messup --- crates/g3-cli/src/retro_tui.rs | 38 ++++++++++++++++++++-------- crates/g3-cli/src/ui_writer_impl.rs | 39 +++++++++++++++++++++-------- 2 files changed, 57 insertions(+), 20 deletions(-) diff --git a/crates/g3-cli/src/retro_tui.rs b/crates/g3-cli/src/retro_tui.rs index 268b21d..d0d7058 100644 --- a/crates/g3-cli/src/retro_tui.rs +++ b/crates/g3-cli/src/retro_tui.rs @@ -34,6 +34,7 @@ pub enum TuiMessage { AgentOutput(String), ToolOutput { name: String, + caption: String, content: String, }, SystemStatus(String), @@ -103,7 +104,7 @@ impl TerminalState { } /// Format tool call output with a box - fn format_tool_output(&mut self, tool_name: &str, content: &str) { + fn format_tool_output(&mut self, tool_name: &str, caption: &str, content: &str) { // Calculate box width (use a reasonable width, accounting for terminal size) let box_width = 80; let border_char = "─"; @@ -122,7 +123,7 @@ impl TerminalState { )); // Add header with tool name (will be styled with green background in draw) - let header_text = format!(" {} ", tool_name.to_uppercase()); + let header_text = format!(" {} | {}", tool_name.to_uppercase(), caption); let padding = box_width - 2 - header_text.len(); self.output_history.push(format!( "{}[TOOL_HEADER]{}{}{}", @@ -189,10 +190,25 @@ impl TerminalState { /// Add text to output history fn add_output(&mut self, text: &str) { - // Split text by newlines and add each line - for line in text.lines() { + let mut lines = text.lines(); + + // Handle the first line specially + if let Some(first_line) = lines.next() { + if let Some(last) = self.output_history.last_mut() { + // Append first fragment to the last element + last.push_str(first_line); + } else { + // No existing elements, just push the first line + self.output_history.push(first_line.to_string()); + } + } + + // Push the remaining lines individually + for line in lines { self.output_history.push(line.to_string()); } + + // Update scroll state // Auto-scroll to bottom only if user hasn't manually scrolled if !self.manual_scroll { let total_lines = self.output_history.len(); @@ -258,16 +274,17 @@ impl RetroTui { TuiMessage::AgentOutput(text) => { state.add_output(&text); } - TuiMessage::ToolOutput { name, content } => { - state.format_tool_output(&name, &content); + TuiMessage::ToolOutput { + name, + caption, + content, + } => { + state.format_tool_output(&name, &caption, &content); } TuiMessage::SystemStatus(status) => { let was_processing = state.status_line == "PROCESSING"; state.status_line = status; - // When transitioning from PROCESSING to READY, add padding - // This ensures we can scroll to see all content if was_processing && state.status_line == "READY" { - state.add_padding(); state.manual_scroll = false; // Reset manual scroll } } @@ -611,9 +628,10 @@ impl RetroTui { } /// Send tool output to the terminal - pub fn tool_output(&self, name: &str, content: &str) { + pub fn tool_output(&self, name: &str, caption: &str, content: &str) { let _ = self.tx.send(TuiMessage::ToolOutput { name: name.to_string(), + caption: caption.to_string(), content: content.to_string(), }); } diff --git a/crates/g3-cli/src/ui_writer_impl.rs b/crates/g3-cli/src/ui_writer_impl.rs index f420d6c..71c7c57 100644 --- a/crates/g3-cli/src/ui_writer_impl.rs +++ b/crates/g3-cli/src/ui_writer_impl.rs @@ -91,7 +91,11 @@ pub struct RetroTuiWriter { impl RetroTuiWriter { pub fn new(tui: RetroTui) -> Self { - Self { tui, current_tool_name: Mutex::new(None), current_tool_output: Mutex::new(Vec::new()) } + Self { + tui, + current_tool_name: Mutex::new(None), + current_tool_output: Mutex::new(Vec::new()), + } } } @@ -127,20 +131,32 @@ impl UiWriter for RetroTuiWriter { // Start collecting tool output *self.current_tool_name.lock().unwrap() = Some(tool_name.to_string()); self.current_tool_output.lock().unwrap().clear(); - self.current_tool_output.lock().unwrap().push(format!("Tool: {}", tool_name)); + self.current_tool_output + .lock() + .unwrap() + .push(format!("Tool: {}", tool_name)); } fn print_tool_arg(&self, key: &str, value: &str) { - self.current_tool_output.lock().unwrap().push(format!("{}: {}", key, value)); + self.current_tool_output + .lock() + .unwrap() + .push(format!("{}: {}", key, value)); } fn print_tool_output_header(&self) { self.current_tool_output.lock().unwrap().push(String::new()); - self.current_tool_output.lock().unwrap().push("Output:".to_string()); + self.current_tool_output + .lock() + .unwrap() + .push("Output:".to_string()); } fn print_tool_output_line(&self, line: &str) { - self.current_tool_output.lock().unwrap().push(line.to_string()); + self.current_tool_output + .lock() + .unwrap() + .push(line.to_string()); } fn print_tool_output_summary(&self, hidden_count: usize) { @@ -152,21 +168,24 @@ impl UiWriter for RetroTuiWriter { } fn print_tool_timing(&self, duration_str: &str) { - self.current_tool_output.lock().unwrap().push(format!("⚡️ {}", duration_str)); - + self.current_tool_output + .lock() + .unwrap() + .push(format!("⚡️ {}", duration_str)); + // Now send the complete tool output as a box if let Some(tool_name) = self.current_tool_name.lock().unwrap().as_ref() { let content = self.current_tool_output.lock().unwrap().join("\n"); - self.tui.tool_output(tool_name, &content); + self.tui.tool_output(tool_name, "...", &content); } - + // Clear the buffers *self.current_tool_name.lock().unwrap() = None; self.current_tool_output.lock().unwrap().clear(); } fn print_agent_prompt(&self) { - self.tui.output("🤖 "); + self.tui.output("💬 "); } fn print_agent_response(&self, content: &str) {