Add fancy ASCII art header for agent mode
The agent mode header now shows: - Agent name in uppercase with box art - Working directory (truncated if too long) - Status indicators for README, AGENTS.md, and Memory loading - Task preview if provided Also exports truncate_for_display and adds truncate_path_for_display helper functions in project_files module.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -140,7 +140,8 @@ fn find_fallback_title(content: &str) -> Option<String> {
|
||||
}
|
||||
|
||||
/// 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::*;
|
||||
|
||||
Reference in New Issue
Block a user