feat(#2196): stamp _body on mcp__bash__run, drop tool-specific JS branch
Backend now stamps `_body` (full `$ <cmd>`) alongside `_summary` (first line) and `_category: "rich"` for mcp__bash__run tool_use entries. The frontend drops the mcp__bash__run-specific branch in renderRichToolUse and uses a generic `if (c._body)` path instead — api.details() with the backend-computed summary and body, no JS knowledge of the tool name.
This commit is contained in:
parent
0f5367f948
commit
b62652c01b
2 changed files with 32 additions and 8 deletions
|
|
@ -1559,14 +1559,11 @@ window.marked = marked;
|
||||||
'answer #' + id + (lines > 1 ? ` · ${lines}L` : ''),
|
'answer #' + id + (lines > 1 ? ` · ${lines}L` : ''),
|
||||||
a, icon);
|
a, icon);
|
||||||
}
|
}
|
||||||
// Bash task runner — show full command in an expandable pre block so
|
// Generic plain-text body: the backend stamps `_body` for tools whose
|
||||||
// multi-line scripts are readable. Summary uses the first line so the
|
// expandable content is plain text (e.g. mcp__bash__run full command).
|
||||||
// row is identifiable without expanding.
|
// Render as a collapsible details row without any tool-specific logic.
|
||||||
if (name === 'mcp__bash__run') {
|
if (c._body) {
|
||||||
const cmd = String(input.cmd || '');
|
return api.details('tool-use', c._summary || name || '?', c._body, icon);
|
||||||
const firstLine = cmd.split('\n')[0];
|
|
||||||
const summary = 'run* $ ' + trim(firstLine.trim(), 72);
|
|
||||||
return api.details('tool-use', summary, '$ ' + cmd, icon);
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -230,6 +230,7 @@ fn enrich_tool_use_entry(entry: &mut Value) {
|
||||||
let icon = tool_icon(&name);
|
let icon = tool_icon(&name);
|
||||||
let summary = fmt_tool_use(&name, &input);
|
let summary = fmt_tool_use(&name, &input);
|
||||||
let rich = is_rich_tool(&name);
|
let rich = is_rich_tool(&name);
|
||||||
|
let body = rich_tool_body(&name, &input);
|
||||||
let Some(obj) = entry.as_object_mut() else {
|
let Some(obj) = entry.as_object_mut() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
@ -238,6 +239,9 @@ fn enrich_tool_use_entry(entry: &mut Value) {
|
||||||
if rich {
|
if rich {
|
||||||
obj.insert("_category".to_owned(), json!("rich"));
|
obj.insert("_category".to_owned(), json!("rich"));
|
||||||
}
|
}
|
||||||
|
if let Some(b) = body {
|
||||||
|
obj.insert("_body".to_owned(), json!(b));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
@ -260,6 +264,29 @@ fn is_rich_tool(name: &str) -> bool {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pre-compute the expandable body text for tools that have one.
|
||||||
|
///
|
||||||
|
/// Returns `Some(body)` when the tool has a meaningful multi-line body that
|
||||||
|
/// the frontend can display in a `<details>` block without tool-specific JS.
|
||||||
|
/// `None` for tools whose body is computed client-side (diffs, markdown) or
|
||||||
|
/// that have no body at all.
|
||||||
|
fn rich_tool_body(name: &str, input: &Value) -> Option<String> {
|
||||||
|
match name {
|
||||||
|
// Full bash command — first line is already in `_summary`; the full
|
||||||
|
// `cmd` (prefixed with `$ `) is the body so multi-line scripts are
|
||||||
|
// readable on expand.
|
||||||
|
"mcp__bash__run" => {
|
||||||
|
let cmd = input.get("cmd").and_then(Value::as_str).unwrap_or("");
|
||||||
|
if cmd.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(format!("$ {cmd}"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn tool_icon(name: &str) -> &'static str {
|
fn tool_icon(name: &str) -> &'static str {
|
||||||
// Exact-match table first, then prefix/contains fallbacks.
|
// Exact-match table first, then prefix/contains fallbacks.
|
||||||
match name {
|
match name {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue