diff --git a/crates/g3-cli/src/ui_writer_impl.rs b/crates/g3-cli/src/ui_writer_impl.rs index b054427..85b04fd 100644 --- a/crates/g3-cli/src/ui_writer_impl.rs +++ b/crates/g3-cli/src/ui_writer_impl.rs @@ -486,7 +486,7 @@ impl UiWriter for ConsoleUiWriter { self.hint_state.handle_hint(ToolParsingHint::Complete); // Handle file operation tools and other compact tools - let is_compact_tool = matches!(tool_name, "read_file" | "write_file" | "str_replace" | "remember" | "screenshot" | "coverage" | "rehydrate" | "code_search" | "plan_approve"); + let is_compact_tool = matches!(tool_name, "read_file" | "write_file" | "str_replace" | "remember" | "screenshot" | "coverage" | "rehydrate" | "code_search" | "plan_approve" | "load_toolset"); if !is_compact_tool { // Reset continuation tracking for non-compact tools *self.last_read_file_path.lock().unwrap() = None; @@ -543,8 +543,15 @@ impl UiWriter for ConsoleUiWriter { String::new() } } else { - // For remember, screenshot, etc. - no path to show - String::new() + // For load_toolset, show the toolset name + if tool_name == "load_toolset" { + args.iter().find(|(k, _)| k == "name") + .map(|(_, v)| v.to_string()) + .unwrap_or_default() + } else { + // For remember, screenshot, etc. - no path to show + String::new() + } } } else { // Shorten path (project -> name/, workspace -> ./, home -> ~) then truncate if still long diff --git a/crates/g3-core/src/streaming.rs b/crates/g3-core/src/streaming.rs index 450e4c1..2d41d00 100644 --- a/crates/g3-core/src/streaming.rs +++ b/crates/g3-core/src/streaming.rs @@ -75,6 +75,7 @@ pub fn format_tool_result_summary( | "rehydrate" | "code_search" | "plan_approve" + | "load_toolset" ); if is_self_handled { @@ -103,6 +104,7 @@ pub fn is_compact_tool(tool_name: &str) -> bool { | "rehydrate" | "code_search" | "plan_approve" + | "load_toolset" ) } @@ -131,6 +133,7 @@ fn format_compact_tool_summary(tool_name: &str, tool_result: &str) -> String { "rehydrate" => format_rehydrate_summary(tool_result), "code_search" => format_code_search_summary(tool_result), "plan_approve" => format_plan_approve_summary(tool_result), + "load_toolset" => format_load_toolset_summary(tool_result), _ => "✅ completed".to_string(), } } @@ -540,6 +543,28 @@ pub fn format_plan_approve_summary(result: &str) -> String { } } +/// Format a load_toolset result summary. +pub fn format_load_toolset_summary(result: &str) -> String { + // Result formats: + // "✅ Loaded toolset 'webdriver' with 8 tools:\n\n..." + // "✅ Toolset 'webdriver' is already loaded. You can use its tools." + // "❌ Unknown toolset 'foo'..." + if result.contains("❌") { + "❌ failed".to_string() + } else if result.contains("already loaded") { + "ℹ️ already loaded".to_string() + } else if let Some(start) = result.find("toolset '") { + let after = &result[start + 9..]; + if let Some(end) = after.find('\'') { + let name = &after[..end]; + return format!("🧩 loaded '{}'", name); + } + "🧩 loaded".to_string() + } else { + "🧩 loaded".to_string() + } +} + // ============================================================================= // Tool Call Deduplication // =============================================================================