use crate::config::Config;
use colored::Colorize;
pub async fn display_individual_tool_header_with_params(
tool_name: &str,
stored_tool_call: &Option<crate::mcp::McpToolCall>,
config: &Config,
tool_index: usize,
) {
display_individual_tool_header_with_context(
tool_name,
stored_tool_call,
config,
tool_index,
None, )
.await;
}
pub async fn display_individual_tool_header_with_context(
tool_name: &str,
stored_tool_call: &Option<crate::mcp::McpToolCall>,
config: &Config,
tool_index: usize,
execution_context: Option<&str>, ) {
let server_name =
crate::session::chat::response::get_tool_server_name_async(tool_name, config).await;
let title = if let Some(context) = execution_context {
format!(
" [{}] {} | {} | {} ",
tool_index,
tool_name.bright_cyan(),
server_name.bright_blue(),
context.bright_yellow()
)
} else {
format!(
" [{}] {} | {} ",
tool_index,
tool_name.bright_cyan(),
server_name.bright_blue()
)
};
let separator_length = 70.max(title.len() + 4);
let dashes = "─".repeat(separator_length - title.len());
let separator = format!("──{}{}──", title, dashes.dimmed());
println!("{}", separator);
if let Some(tool_call) = stored_tool_call {
if config.get_log_level().is_info_enabled() || config.get_log_level().is_debug_enabled() {
display_tool_parameters_full(tool_call, config);
println!(); }
}
}
pub fn display_tool_output_smart(output_str: &str) {
let lines: Vec<&str> = output_str.lines().collect();
if lines.len() <= 20 && output_str.chars().count() <= 2000 {
println!("{}", output_str);
} else if lines.len() > 20 {
for line in lines.iter().take(15) {
println!("{}", line);
}
println!("... [{} more lines]", lines.len().saturating_sub(15));
} else {
let truncated: String = output_str.chars().take(1997).collect();
println!("{}...", truncated);
}
}
pub fn display_tool_parameters_full(tool_call: &crate::mcp::McpToolCall, config: &Config) {
if let Ok(params_obj) = serde_json::from_value::<serde_json::Map<String, serde_json::Value>>(
tool_call.parameters.clone(),
) {
if !params_obj.is_empty() {
let max_key_length = params_obj
.keys()
.map(|k| k.len())
.max()
.unwrap_or(0)
.min(20);
for (key, value) in params_obj.iter() {
let formatted_value = if config.get_log_level().is_debug_enabled() {
format_parameter_value_full(value)
} else {
format_parameter_value_smart(value)
};
println!(
"{}: {}",
format!("{:width$}", key, width = max_key_length).bright_blue(),
formatted_value.white()
);
}
}
} else {
let params_str = serde_json::to_string(&tool_call.parameters).unwrap_or_default();
if params_str != "null" {
if config.get_log_level().is_debug_enabled() {
println!("params: {}", params_str);
} else if params_str.chars().count() > 100 {
let truncated: String = params_str.chars().take(97).collect();
println!("params: {}...", truncated);
} else {
println!("params: {}", params_str);
}
}
}
}
fn format_parameter_value_smart(value: &serde_json::Value) -> String {
match value {
serde_json::Value::String(s) => {
if s.is_empty() {
"\"\"".bright_black().to_string()
} else if s.chars().count() > 100 {
format!("\"{}...\"", s.chars().take(97).collect::<String>())
} else if s.contains('\n') {
let lines: Vec<&str> = s.lines().collect();
let first_line = lines.first().unwrap_or(&"");
let first_line_chars: Vec<char> = first_line.chars().collect();
if first_line_chars.len() > 80 {
format!(
"\"{}...\" [+{} lines]",
first_line_chars.into_iter().take(77).collect::<String>(),
lines.len().saturating_sub(1)
)
} else if lines.len() > 1 {
format!(
"\"{}\" [+{} lines]",
first_line,
lines.len().saturating_sub(1)
)
} else {
format!("\"{}\"", first_line)
}
} else {
format!("\"{}\"", s)
}
}
serde_json::Value::Bool(b) => b.to_string(),
serde_json::Value::Number(n) => n.to_string(),
serde_json::Value::Array(arr) => {
if arr.is_empty() {
"[]".to_string()
} else if arr.len() > 3 {
format!("[{} items]", arr.len())
} else {
let items: Vec<String> = arr
.iter()
.take(3)
.map(|item| match item {
serde_json::Value::String(s) => format!(
"\"{}\"",
if s.chars().count() > 20 {
format!("{}...", s.chars().take(17).collect::<String>())
} else {
s.clone()
}
),
_ => item.to_string(),
})
.collect();
format!("[{}]", items.join(", "))
}
}
serde_json::Value::Object(obj) => {
if obj.is_empty() {
"{}".to_string()
} else {
let obj_str = serde_json::to_string(value).unwrap_or_default();
if obj_str.chars().count() > 100 {
format!("{{...}} ({} keys)", obj.len())
} else {
obj_str
}
}
}
serde_json::Value::Null => "null".bright_black().to_string(),
}
}
fn format_parameter_value_full(value: &serde_json::Value) -> String {
match value {
serde_json::Value::String(s) => format!("\"{}\"", s),
_ => serde_json::to_string_pretty(value).unwrap_or_else(|_| value.to_string()),
}
}