tool card UI redesign: semantic icons, inline diff persistence, tool detail page, MCP-friendly titles
Nightly Build / build (push) Successful in 6m38s

This commit is contained in:
2026-07-21 23:39:41 +01:00
parent 8e891fbced
commit c11702c3d3
44 changed files with 1103 additions and 50 deletions
+13
View File
@@ -43,6 +43,12 @@ pub enum ServerEvent {
message_id: i64,
name: String,
arguments: Value,
/// Friendly, static card title ("Edit File", "Read File", or an MCP tool's
/// resolved friendly name). Separate from `name` (the raw LLM function id).
display_name: String,
/// Semantic icon key (`edit`/`read`/`shell`/`mcp`/…) the frontend maps to a
/// glyph + accent color. Never a glyph — the core commits to meaning, not look.
icon: String,
/// Concise human-readable label (≤60 chars): tool + primary argument.
label_short: String,
/// Verbose human-readable label (≤120 chars): tool + all meaningful arguments.
@@ -62,6 +68,13 @@ pub enum ServerEvent {
/// server; the frontend treats an absent/unknown value as plain text, so
/// older clients degrade gracefully.
result_type: String,
/// For a file-write tool: the file content before/after the write, so the
/// card renders the diff inline even for an auto-allowed write (one that
/// never emitted a `PendingWrite`). Absent for non-write tools.
#[serde(skip_serializing_if = "Option::is_none")]
preview_old: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
preview_new: Option<String>,
},
/// A tool call failed. DB status: error.
ToolError {
+24
View File
@@ -72,6 +72,30 @@ pub trait Tool: Send + Sync {
self.name().to_string()
}
/// Friendly, **static** display name for this tool ("Edit File", "Read File"),
/// shown as the card title in the chat UI — separate from [`name`](Self::name),
/// which stays the raw LLM function id. Several tools map to the same friendly
/// verb (e.g. `write_file`/`edit_file`/`insert_at_line` → "Edit File"). The
/// default returns the raw name so unmapped tools still render something.
fn display_name(&self) -> &str {
self.name()
}
/// Semantic icon key for the chat card — **not** a glyph. The frontend maps the
/// key to a concrete icon + accent color (themeable), so the core commits to a
/// meaning, never a look. Known keys: `edit`, `read`, `list`, `search`, `shell`,
/// `subagent`, `image`, `config`, `introspection`. The default derives from
/// [`category`](Self::category).
fn icon(&self) -> &str {
match self.category() {
ToolCategory::Filesystem => "file",
ToolCategory::Shell => "shell",
ToolCategory::Subagent => "subagent",
ToolCategory::Introspection => "introspection",
ToolCategory::Config => "config",
}
}
/// If this invocation targets a single file the user can open in the file
/// viewer, return its path (relative to the project root, or absolute).
/// Tools that target a directory (list/grep) or no file at all return