diff --git a/crates/g3-cli/src/lib.rs b/crates/g3-cli/src/lib.rs index e9fa0fd..669b197 100644 --- a/crates/g3-cli/src/lib.rs +++ b/crates/g3-cli/src/lib.rs @@ -28,7 +28,7 @@ use tracing::{debug, error}; use g3_core::error_handling::{classify_error, ErrorType, RecoverableError}; use machine_ui_writer::MachineUiWriter; use metrics::{format_elapsed_time, generate_turn_histogram, TurnMetrics}; -use project_files::{extract_readme_heading, read_agents_config, read_project_memory, read_project_readme}; +use project_files::{extract_readme_heading, read_agents_config, read_project_memory, read_project_readme, truncate_for_display, truncate_path_for_display}; use simple_output::SimpleOutput; use ui_writer_impl::ConsoleUiWriter; @@ -539,9 +539,6 @@ async fn run_agent_mode( ))? }; - output.print(&format!("๐Ÿค– Running as agent: {}", agent_name)); - output.print(&format!("๐Ÿ“ Working directory: {:?}", workspace_dir)); - // Load config let mut config = g3_config::Config::load(config_path)?; @@ -562,20 +559,23 @@ async fn run_agent_mode( let system_prompt = get_agent_system_prompt(&agent_prompt, true); // Load AGENTS.md, README, and memory - same as normal mode - let agents_content = read_agents_config(&workspace_dir); - let readme_content = read_project_readme(&workspace_dir); - let memory_content = read_project_memory(&workspace_dir); + let agents_content_opt = read_agents_config(&workspace_dir); + let readme_content_opt = read_project_readme(&workspace_dir); + let memory_content_opt = read_project_memory(&workspace_dir); + let has_agents = agents_content_opt.is_some(); + let has_readme = readme_content_opt.is_some(); + let has_memory = memory_content_opt.is_some(); // Combine all content for the agent's context let combined_content = { let mut parts = Vec::new(); - if let Some(agents) = agents_content { + if let Some(agents) = agents_content_opt { parts.push(agents); } - if let Some(readme) = readme_content { + if let Some(readme) = readme_content_opt { parts.push(readme); } - if let Some(memory) = memory_content { + if let Some(memory) = memory_content_opt { parts.push(memory); } if parts.is_empty() { @@ -585,6 +585,31 @@ async fn run_agent_mode( } }; + // Print fancy agent header + let agent_upper = agent_name.to_uppercase(); + output.print(""); + output.print("โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”"); + output.print(&format!("โ”‚ ๐Ÿค– AGENT: {:<46} โ”‚", agent_upper)); + output.print("โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค"); + output.print(&format!("โ”‚ ๐Ÿ“ {:<53} โ”‚", + truncate_path_for_display(&workspace_dir, 53))); + output.print("โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค"); + + // Show what was loaded + let readme_status = if has_readme { "โœ“" } else { "ยท" }; + let agents_status = if has_agents { "โœ“" } else { "ยท" }; + let memory_status = if has_memory { "โœ“" } else { "ยท" }; + output.print(&format!("โ”‚ {} README {} AGENTS.md {} Memory โ”‚", + readme_status, agents_status, memory_status)); + output.print("โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜"); + output.print(""); + + // Show task if provided + if let Some(ref task) = task { + output.print(&format!("๐Ÿ“‹ Task: {}", truncate_for_display(task, 60))); + output.print(""); + } + // Create agent with custom system prompt let ui_writer = ConsoleUiWriter::new(); // Set agent mode on UI writer for visual differentiation (light gray tool names) diff --git a/crates/g3-cli/src/project_files.rs b/crates/g3-cli/src/project_files.rs index e74887d..adbeeba 100644 --- a/crates/g3-cli/src/project_files.rs +++ b/crates/g3-cli/src/project_files.rs @@ -140,7 +140,8 @@ fn find_fallback_title(content: &str) -> Option { } /// Truncate a string for display, adding ellipsis if needed. -fn truncate_for_display(s: &str, max_len: usize) -> String { +/// Used for displaying long strings in fixed-width UI elements. +pub fn truncate_for_display(s: &str, max_len: usize) -> String { if s.len() > max_len { format!("{}...", &s[..max_len - 3]) } else { @@ -148,6 +149,20 @@ fn truncate_for_display(s: &str, max_len: usize) -> String { } } +/// Truncate a path for display, showing the end portion if too long. +/// For paths, we want to show the most relevant part (the end). +pub fn truncate_path_for_display(path: &std::path::Path, max_len: usize) -> String { + let path_str = path.display().to_string(); + if path_str.len() > max_len { + // Show the end of the path with ... prefix + let start = path_str.len() - (max_len - 3); + // Find a path separator to break at cleanly if possible + format!("...{}", &path_str[start..]) + } else { + path_str + } +} + #[cfg(test)] mod tests { use super::*;