diff --git a/codi-rs/src/main.rs b/codi-rs/src/main.rs index 96c8ef88..5c483e90 100644 --- a/codi-rs/src/main.rs +++ b/codi-rs/src/main.rs @@ -75,8 +75,8 @@ struct Cli { #[arg(short = 'y', long)] yes: bool, - /// Show verbose output - #[arg(long)] + /// Show verbose output (enables tool call visibility) + #[arg(short = 'v', long)] verbose: bool, /// Show debug output @@ -234,7 +234,7 @@ async fn main() -> anyhow::Result<()> { } // Start interactive REPL - run_repl(&config, cli.yes).await + run_repl(&config, cli.yes, cli.verbose).await } async fn handle_command(command: Commands) -> anyhow::Result<()> { @@ -495,7 +495,17 @@ async fn handle_prompt( Ok(()) } -async fn run_repl(config: &config::ResolvedConfig, auto_approve: bool) -> anyhow::Result<()> { +async fn run_repl(config: &config::ResolvedConfig, auto_approve: bool, verbose: bool) -> anyhow::Result<()> { // Use new terminal-style REPL instead of full-screen TUI - run_terminal_repl(config, auto_approve).await + // Pass verbose flag to enable tool visibility + let debug_mode = verbose || std::env::var("CODI_DEBUG").is_ok(); + run_terminal_repl(config, auto_approve, debug_mode).await +} + +async fn load_session(app: &mut App, session_name: &str) -> anyhow::Result<()> { + // Try to load by exact name first, then by fuzzy match + if let Err(_) = app.load_session(session_name).await { + return Err(anyhow::anyhow!("Session not found: {}", session_name)); + } + Ok(()) } diff --git a/codi-rs/src/orchestrate/ipc/transport.rs b/codi-rs/src/orchestrate/ipc/transport.rs index 2eacd70d..cf2451ae 100644 --- a/codi-rs/src/orchestrate/ipc/transport.rs +++ b/codi-rs/src/orchestrate/ipc/transport.rs @@ -8,7 +8,10 @@ use std::path::Path; use tokio::io::{AsyncRead, AsyncWrite}; -pub type IpcStream = Box; +pub trait IpcStreamTrait: AsyncRead + AsyncWrite {} +impl IpcStreamTrait for T {} + +pub type IpcStream = Box; #[cfg(unix)] use tokio::net::UnixListener; diff --git a/codi-rs/src/tui/app.rs b/codi-rs/src/tui/app.rs index 74abd047..b91893ba 100644 --- a/codi-rs/src/tui/app.rs +++ b/codi-rs/src/tui/app.rs @@ -310,6 +310,11 @@ impl App { self.auto_approve_all = auto_approve; } + /// Get the auto-approve-all flag value. + pub fn auto_approve_all(&self) -> bool { + self.auto_approve_all + } + /// Build an `AgentConfig` from the stored `ResolvedConfig`, or use defaults. fn build_agent_config(&self) -> AgentConfig { if let Some(ref config) = self.config { @@ -1015,11 +1020,6 @@ impl App { } } - /// Get the auto-approve-all flag value. - pub fn auto_approve_all(&self) -> bool { - self.auto_approve_all - } - /// Compact conversation context by summarizing older messages. /// Returns the number of messages that were summarized. pub fn compact_conversation(&mut self) -> usize { diff --git a/codi-rs/src/tui/terminal_ui.rs b/codi-rs/src/tui/terminal_ui.rs index 03ff0ab1..08856097 100644 --- a/codi-rs/src/tui/terminal_ui.rs +++ b/codi-rs/src/tui/terminal_ui.rs @@ -31,14 +31,13 @@ use super::commands::{execute_async_command, handle_command, CommandResult}; pub async fn run_terminal_repl( config: &ResolvedConfig, auto_approve: bool, + debug_mode: bool, ) -> anyhow::Result<()> { // Print welcome banner print_welcome(config)?; - // Check if debug mode is enabled via environment variable - let debug_mode = std::env::var("CODI_DEBUG").is_ok(); if debug_mode { - println!("{} Debug mode enabled - tool calls will be shown", "⚙".yellow()); + println!("⚙ Debug mode enabled - tool calls will be shown"); println!(); } @@ -64,9 +63,9 @@ pub async fn run_terminal_repl( if trimmed == "/debug" { app.debug_mode = !app.debug_mode; if app.debug_mode { - println!("{} Debug mode enabled - tool calls will be shown", "⚙".yellow()); + println!("⚙ Debug mode enabled - tool calls will be shown"); } else { - println!("{} Debug mode disabled", "⚙".yellow()); + println!("⚙ Debug mode disabled"); } continue; } @@ -265,12 +264,9 @@ impl TerminalApp { println!(); print_tool_start(&name); } - StreamEvent::ToolResult(_result, is_error) => { - if is_error { - print_tool_error(); - } else { - print_tool_success(); - } + StreamEvent::ToolResult(result, is_error) => { + // Show result in debug mode + print_tool_result(&result, is_error); } StreamEvent::TurnComplete(_stats) => { break; @@ -361,31 +357,42 @@ fn print_tool_start(name: &str) { let _ = stdout.flush(); } -fn print_tool_success() { +fn print_tool_result(result: &str, is_error: bool) { use crossterm::style::{Color, Print, ResetColor, SetForegroundColor}; use crossterm::ExecutableCommand; use std::io::{self, Write}; let mut stdout = io::stdout(); - let _ = stdout.execute(Print("\r")); - let _ = stdout.execute(SetForegroundColor(Color::Green)); - let _ = stdout.execute(Print("✓ Completed")); - let _ = stdout.execute(ResetColor); - let _ = stdout.execute(Print("\n")); - let _ = stdout.flush(); -} - -fn print_tool_error() { - use crossterm::style::{Color, Print, ResetColor, SetForegroundColor}; - use crossterm::ExecutableCommand; - use std::io::{self, Write}; - let mut stdout = io::stdout(); - let _ = stdout.execute(Print("\r")); - let _ = stdout.execute(SetForegroundColor(Color::Red)); - let _ = stdout.execute(Print("✗ Failed")); + // Truncate very long results + let display_result = if result.len() > 500 { + format!("{}... [truncated {} more chars]", &result[..500], result.len() - 500) + } else { + result.to_string() + }; + + // Format as indented JSON if possible + let formatted = if let Ok(json) = serde_json::from_str::(result) { + serde_json::to_string_pretty(&json).unwrap_or_else(|_| display_result) + } else { + display_result + }; + + println!(); + + if is_error { + let _ = stdout.execute(SetForegroundColor(Color::Red)); + let _ = stdout.execute(Print("✗ Failed:\n")); + } else { + let _ = stdout.execute(SetForegroundColor(Color::Green)); + let _ = stdout.execute(Print("✓ Result:\n")); + } let _ = stdout.execute(ResetColor); - let _ = stdout.execute(Print("\n")); + + // Print indented result + for line in formatted.lines() { + let _ = stdout.execute(Print(format!(" {}\n", line))); + } let _ = stdout.flush(); }