From 45970824d9af7fef294c548e3e60b548d0afd5c5 Mon Sep 17 00:00:00 2001 From: Dhanji Prasanna Date: Mon, 15 Sep 2025 08:40:27 +1000 Subject: [PATCH] cleaned up logging --- Cargo.lock | 13 ++++++++++ crates/g3-cli/Cargo.toml | 2 +- crates/g3-cli/src/lib.rs | 28 ++++++++++++++++---- crates/g3-core/src/lib.rs | 54 +++++++++++++++++++++++++-------------- 4 files changed, 72 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e2b33a..6e41156 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1264,6 +1264,15 @@ version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + [[package]] name = "memchr" version = "2.7.5" @@ -2302,10 +2311,14 @@ version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" dependencies = [ + "matchers", "nu-ansi-term", + "once_cell", + "regex-automata", "sharded-slab", "smallvec", "thread_local", + "tracing", "tracing-core", "tracing-log", ] diff --git a/crates/g3-cli/Cargo.toml b/crates/g3-cli/Cargo.toml index 818f0cd..08e55e8 100644 --- a/crates/g3-cli/Cargo.toml +++ b/crates/g3-cli/Cargo.toml @@ -11,7 +11,7 @@ clap = { workspace = true } tokio = { workspace = true } anyhow = { workspace = true } tracing = { workspace = true } -tracing-subscriber = { workspace = true } +tracing-subscriber = { workspace = true, features = ["env-filter"] } serde = { workspace = true } serde_json = { workspace = true } rustyline = "17.0.1" diff --git a/crates/g3-cli/src/lib.rs b/crates/g3-cli/src/lib.rs index b9a0404..4c81913 100644 --- a/crates/g3-cli/src/lib.rs +++ b/crates/g3-cli/src/lib.rs @@ -36,14 +36,32 @@ pub struct Cli { pub async fn run() -> Result<()> { let cli = Cli::parse(); - // Initialize logging - let level = if cli.verbose { - tracing::Level::DEBUG + // Initialize logging with filtering + use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; + + // Create a filter that suppresses llama_cpp logs unless in verbose mode + let filter = if cli.verbose { + EnvFilter::from_default_env() + .add_directive(format!("{}=debug", env!("CARGO_PKG_NAME")).parse().unwrap()) + .add_directive("g3_core=debug".parse().unwrap()) + .add_directive("g3_cli=debug".parse().unwrap()) + .add_directive("g3_execution=debug".parse().unwrap()) + .add_directive("g3_providers=debug".parse().unwrap()) } else { - tracing::Level::INFO + EnvFilter::from_default_env() + .add_directive(format!("{}=info", env!("CARGO_PKG_NAME")).parse().unwrap()) + .add_directive("g3_core=info".parse().unwrap()) + .add_directive("g3_cli=info".parse().unwrap()) + .add_directive("g3_execution=info".parse().unwrap()) + .add_directive("g3_providers=info".parse().unwrap()) + .add_directive("llama_cpp=off".parse().unwrap()) // Suppress all llama_cpp logs + .add_directive("llama=off".parse().unwrap()) // Suppress all llama.cpp logs }; - tracing_subscriber::fmt().with_max_level(level).init(); + tracing_subscriber::registry() + .with(tracing_subscriber::fmt::layer()) + .with(filter) + .init(); info!("Starting G3 AI Coding Agent"); diff --git a/crates/g3-core/src/lib.rs b/crates/g3-core/src/lib.rs index d1a4b93..e605586 100644 --- a/crates/g3-core/src/lib.rs +++ b/crates/g3-core/src/lib.rs @@ -147,12 +147,17 @@ impl StreamingToolParser { ); } } - + // Try to fix mixed quote issues (single quotes in JSON) let fixed_mixed_quotes = fix_mixed_quotes_in_json(&json_str); if fixed_mixed_quotes != json_str { - if let Ok(tool_call) = serde_json::from_str::(&fixed_mixed_quotes) { - info!("Successfully parsed tool call after fixing mixed quotes: {:?}", tool_call); + if let Ok(tool_call) = + serde_json::from_str::(&fixed_mixed_quotes) + { + info!( + "Successfully parsed tool call after fixing mixed quotes: {:?}", + tool_call + ); // Reset parser state self.in_tool_call = false; self.tool_start_pos = None; @@ -160,7 +165,10 @@ impl StreamingToolParser { return Some((tool_call, end_pos)); } else { - info!("Failed to parse JSON even after fixing mixed quotes: {}", fixed_mixed_quotes); + info!( + "Failed to parse JSON even after fixing mixed quotes: {}", + fixed_mixed_quotes + ); } } else { info!("Failed to parse JSON (no fixes applied): {}", json_str); @@ -442,7 +450,7 @@ The tool will execute immediately and you'll receive the result (success or erro - Format: {{\"tool\": \"shell\", \"args\": {{\"command\": \"your_command_here\"}}}} - Example: {{\"tool\": \"shell\", \"args\": {{\"command\": \"ls ~/Downloads\"}}}} -- **final_output**: Signal task completion with a summary of work done in markdown format +- **final_output**: Signal task completion with a detailed summary of work done in markdown format - Format: {{\"tool\": \"final_output\", \"args\": {{\"summary\": \"what_was_accomplished\"}}}} # Instructions @@ -769,6 +777,22 @@ The tool will execute immediately and you'll receive the result (success or erro ); } + // Check if this was a final_output tool call - if so, stop the conversation + if tool_call.tool == "final_output" { + // For final_output, don't add the tool call and result to context + // Just add the display content and return immediately + full_response.push_str(final_display_content); + if let Some(summary) = tool_call.args.get("summary") { + if let Some(summary_str) = summary.as_str() { + full_response.push_str(&format!("\n\n=> {}", summary_str)); + } + } + println!(); // New line after final output + let ttft = + first_token_time.unwrap_or_else(|| stream_start.elapsed()); + return Ok((full_response, ttft)); + } + // Closure marker with timing println!("└─ ⚡️ {}", Self::format_duration(exec_duration)); println!(); @@ -803,14 +827,6 @@ The tool will execute immediately and you'll receive the result (success or erro tool_call.tool, tool_result )); - // Check if this was a final_output tool call - if so, stop the conversation - if tool_call.tool == "final_output" { - println!(); // New line after final output - let ttft = - first_token_time.unwrap_or_else(|| stream_start.elapsed()); - return Ok((full_response, ttft)); - } - tool_executed = true; // Break out of current stream to start a new one with updated context break; @@ -907,12 +923,12 @@ The tool will execute immediately and you'll receive the result (success or erro "final_output" => { if let Some(summary) = tool_call.args.get("summary") { if let Some(summary_str) = summary.as_str() { - Ok(format!("📋 Final Output: {}", summary_str)) + Ok(format!("{}", summary_str)) } else { - Ok("📋 Task completed".to_string()) + Ok("✅ Task completed".to_string()) } } else { - Ok("📋 Task completed".to_string()) + Ok("✅ Task completed".to_string()) } } _ => { @@ -1085,12 +1101,12 @@ fn fix_nested_quotes_in_shell_command(json_str: &str) -> String { fn fix_mixed_quotes_in_json(json_str: &str) -> String { // This handles cases where the LLM uses single quotes in JSON values // Example: {"tool": "shell", "args": {"command": 'echo "hello"'}} - + let mut result = String::new(); let mut chars = json_str.chars().peekable(); let mut in_string = false; let mut string_delimiter = '"'; - + while let Some(ch) = chars.next() { match ch { '"' if !in_string => { @@ -1130,7 +1146,7 @@ fn fix_mixed_quotes_in_json(json_str: &str) -> String { } } } - + result }