From acdecbb729329f466b8c1c8b0842fac1cd876e62 Mon Sep 17 00:00:00 2001 From: Yeachan-Heo Date: Wed, 1 Apr 2026 02:20:59 +0000 Subject: [PATCH] feat: improved tool call display with box rendering, colored output --- .claude/sessions/session-1775010002596.json | 1 + .../sessions/session-1775010047738.json | 1 + rust/crates/rusty-claude-cli/src/main.rs | 80 +++++++++++++++---- 3 files changed, 65 insertions(+), 17 deletions(-) create mode 100644 .claude/sessions/session-1775010002596.json create mode 100644 rust/.claude/sessions/session-1775010047738.json diff --git a/.claude/sessions/session-1775010002596.json b/.claude/sessions/session-1775010002596.json new file mode 100644 index 0000000..9e77d71 --- /dev/null +++ b/.claude/sessions/session-1775010002596.json @@ -0,0 +1 @@ +{"messages":[{"blocks":[{"text":"Read the file Cargo.toml and tell me the package name","type":"text"}],"role":"user"},{"blocks":[{"text":"\n\n\nfind_file\n{\"pattern\": \"Cargo.toml\", \"path\": \"/home/bellman/Workspace/clawd-code\"}\n\n\nLet me find the relevant Cargo.toml file(s) in the project.\n\n\nbash\n{\"command\": \"find /home/bellman/Workspace/clawd-code -name 'Cargo.toml' -maxdepth 4 | head -20\"}\n\n\n\nread_file\n{\"file_path\": \"/home/bellman/Workspace/clawd-code/rust/Cargo.toml\"}\n\n\n\nread_file\n{\"file_path\": \"/home/bellman/Workspace/clawd-code/rust/crates/rusty-claude-cli/Cargo.toml\"}\n\n\nHere are the Cargo.toml files found:\n\n1. **Workspace root** (`rust/Cargo.toml`) — This is a virtual workspace manifest (no `[package]` section). It lists members:\n - `crates/rusty-claude-cli`\n - `crates/rusty-claude-core`\n\n2. **CLI crate** (`rust/crates/rusty-claude-cli/Cargo.toml`) — The package name is:\n\n > **`rusty-claude-cli`** (version `0.1.0`)","type":"text"}],"role":"assistant","usage":{"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"input_tokens":3074,"output_tokens":352}}],"version":1} \ No newline at end of file diff --git a/rust/.claude/sessions/session-1775010047738.json b/rust/.claude/sessions/session-1775010047738.json new file mode 100644 index 0000000..d45e491 --- /dev/null +++ b/rust/.claude/sessions/session-1775010047738.json @@ -0,0 +1 @@ +{"messages":[],"version":1} \ No newline at end of file diff --git a/rust/crates/rusty-claude-cli/src/main.rs b/rust/crates/rusty-claude-cli/src/main.rs index ce5a0e4..7fee838 100644 --- a/rust/crates/rusty-claude-cli/src/main.rs +++ b/rust/crates/rusty-claude-cli/src/main.rs @@ -2099,28 +2099,74 @@ fn slash_command_completion_candidates() -> Vec { } fn format_tool_call_start(name: &str, input: &str) -> String { + let parsed: serde_json::Value = + serde_json::from_str(input).unwrap_or(serde_json::Value::String(input.to_string())); + + let detail = match name { + "bash" | "Bash" => parsed + .get("command") + .and_then(|v| v.as_str()) + .map(|cmd| truncate_for_summary(cmd, 120)) + .unwrap_or_default(), + "read_file" | "Read" => parsed + .get("file_path") + .or_else(|| parsed.get("path")) + .and_then(|v| v.as_str()) + .unwrap_or("?") + .to_string(), + "write_file" | "Write" => { + let path = parsed + .get("file_path") + .or_else(|| parsed.get("path")) + .and_then(|v| v.as_str()) + .unwrap_or("?"); + let lines = parsed + .get("content") + .and_then(|v| v.as_str()) + .map(|c| c.lines().count()) + .unwrap_or(0); + format!("{path} ({lines} lines)") + } + "edit_file" | "Edit" => { + let path = parsed + .get("file_path") + .or_else(|| parsed.get("path")) + .and_then(|v| v.as_str()) + .unwrap_or("?"); + path.to_string() + } + "glob_search" | "Glob" => parsed + .get("pattern") + .and_then(|v| v.as_str()) + .unwrap_or("?") + .to_string(), + "grep_search" | "Grep" => parsed + .get("pattern") + .and_then(|v| v.as_str()) + .unwrap_or("?") + .to_string(), + "web_search" | "WebSearch" => parsed + .get("query") + .and_then(|v| v.as_str()) + .unwrap_or("?") + .to_string(), + _ => summarize_tool_payload(input), + }; + + let border = "─".repeat(name.len() + 6); format!( - "Tool call - Name {name} - Input {}", - summarize_tool_payload(input) + "\x1b[38;5;245m╭─ \x1b[1;36m{name}\x1b[0;38;5;245m ─╮\x1b[0m\n\x1b[38;5;245m│\x1b[0m {detail}\n\x1b[38;5;245m╰{border}╯\x1b[0m" ) } fn format_tool_result(name: &str, output: &str, is_error: bool) -> String { - let status = if is_error { "error" } else { "ok" }; - format!( - "### Tool `{name}` - -- Status: {status} -- Output: - -```json -{} -``` -", - prettify_tool_payload(output) - ) + let icon = if is_error { + "\x1b[1;31m✗\x1b[0m" + } else { + "\x1b[1;32m✓\x1b[0m" + }; + let summary = truncate_for_summary(output.trim(), 200); + format!("{icon} \x1b[38;5;245m{name}:\x1b[0m {summary}") } fn summarize_tool_payload(payload: &str) -> String {