Przeglądaj źródła

feat: improved tool call display with box rendering, colored output

Yeachan-Heo 2 miesięcy temu
rodzic
commit
0d657d6400

+ 1 - 0
.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<tool_use>\nfind_file\n{\"pattern\": \"Cargo.toml\", \"path\": \"/home/bellman/Workspace/clawd-code\"}\n</tool_use>\n\nLet me find the relevant Cargo.toml file(s) in the project.\n\n<tool_use>\nbash\n{\"command\": \"find /home/bellman/Workspace/clawd-code -name 'Cargo.toml' -maxdepth 4 | head -20\"}\n</tool_use>\n\n<tool_use>\nread_file\n{\"file_path\": \"/home/bellman/Workspace/clawd-code/rust/Cargo.toml\"}\n</tool_use>\n\n<tool_use>\nread_file\n{\"file_path\": \"/home/bellman/Workspace/clawd-code/rust/crates/rusty-claude-cli/Cargo.toml\"}\n</tool_use>\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}

+ 1 - 0
rust/.claude/sessions/session-1775010047738.json

@@ -0,0 +1 @@
+{"messages":[],"version":1}

+ 63 - 17
rust/crates/rusty-claude-cli/src/main.rs

@@ -2099,28 +2099,74 @@ fn slash_command_completion_candidates() -> Vec<String> {
 }
 
 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 {