fix(agent): strip tool_use_error tags and render errors in red
When a tool call fails, claude wraps the result text in
<tool_use_error>...</tool_use_error> XML tags. The terminal was
displaying these raw, producing output like:
'<tool_use_error>File has not been read yet.</tool_use_error>'
Fix renderToolResult in app.js:
- Check c.is_error on the tool_result content block.
- Strip the <tool_use_error>...</tool_use_error> wrapper from the text.
- Render error results with a '✗' prefix under '.tool-result.error'
(flat, ≤120c) or '.tool-result-block.error' (<details>, longer text).
Add .live .tool-result.error { color: var(--red); } to terminal.css
so error results are visually distinct (red, same as turn-end-fail).
Update terminal-rendering.md row taxonomy to document the two new
error row classes.
Closes #2104.
This commit is contained in:
parent
3c10b00460
commit
57f936af63
3 changed files with 20 additions and 2 deletions
|
|
@ -63,6 +63,8 @@ parent's negative pull.
|
|||
| `.tool-result` (flat) | `← <txt>` | muted | short `tool_result` (≤120c, non-recv) | stream-json |
|
||||
| `.tool-result-block` `<details>` | `Nl · headline` | muted, body is text | long generic `tool_result` | stream-json |
|
||||
| `.tool-result-block` `<details open>` | `recv ← <txt>` | muted, body is markdown | `tool_result` correlated to a prior `recv` tool_use via id | stream-json |
|
||||
| `.tool-result.error` (flat) | `✗ <msg>` | red | `tool_result` with `is_error: true` (≤120c); `<tool_use_error>` wrapper stripped | stream-json |
|
||||
| `.tool-result-block.error` `<details>` | `Nl · headline` | red, body is text | long error `tool_result` (`is_error: true`); wrapper stripped | stream-json |
|
||||
| `.tool-use` | `⌁ task <id> started · <desc> [type]` | cyan | claude Task-tool subagent start (dead path — `Task` omitted from agent allow-list) | `renderTaskEvent` |
|
||||
| `.turn-end-ok` / `.turn-end-fail` / `.tool-result` | `⌁ task <id> ✓/✗/◌ <status> · <desc> · → <output_file>` | green / red / muted | claude Task-tool result (dead path for agents) | `renderTaskEvent` |
|
||||
| `.note` | `· <text>` | muted | harness chatter | `LiveEvent::Note` |
|
||||
|
|
|
|||
|
|
@ -1684,9 +1684,16 @@ window.marked = marked;
|
|||
// grows with the session — entries are tiny strings.
|
||||
const toolNameById = new Map();
|
||||
function renderToolResult(c, api) {
|
||||
const txt = Array.isArray(c.content)
|
||||
const rawTxt = Array.isArray(c.content)
|
||||
? c.content.map(p => p.text || '').join('')
|
||||
: (c.content || '');
|
||||
// Strip the <tool_use_error>…</tool_use_error> wrapper that claude
|
||||
// emits when a tool call fails — the tags are an implementation detail
|
||||
// and add noise to the terminal display.
|
||||
const isError = !!c.is_error;
|
||||
const txt = isError
|
||||
? rawTxt.replace(/^<tool_use_error>([\s\S]*)<\/tool_use_error>$/, '$1').trim()
|
||||
: rawTxt;
|
||||
const sourceName = c.tool_use_id ? toolNameById.get(c.tool_use_id) : null;
|
||||
const isMessageBearing = sourceName === 'mcp__hyperhive__recv';
|
||||
// When an ask's tool_result lands the broker has just
|
||||
|
|
@ -1707,6 +1714,14 @@ window.marked = marked;
|
|||
const headline = trimmed.slice(0, 90) + '…';
|
||||
return `${lines}L · ${headline}`;
|
||||
})();
|
||||
if (isError) {
|
||||
if (!txt.trim() || txt.length <= 120) {
|
||||
api.row('tool-result error', '✗ ' + summaryBody);
|
||||
} else {
|
||||
api.details('tool-result-block error', summaryBody, txt);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Flat row: keep the `←` glyph in the prefix column. Details rows
|
||||
// drop it — the `▸/▾` disclosure marker sits in that column via CSS.
|
||||
if (isMessageBearing && txt.trim()) {
|
||||
|
|
|
|||
|
|
@ -120,7 +120,8 @@
|
|||
.live .text { color: var(--fg); }
|
||||
.live .thinking { color: var(--muted); font-style: italic; }
|
||||
.live .tool-use { color: var(--cyan); }
|
||||
.live .tool-result { color: var(--muted); }
|
||||
.live .tool-result { color: var(--muted); }
|
||||
.live .tool-result.error { color: var(--red); }
|
||||
.live .result { color: var(--green); }
|
||||
.live .note { color: var(--muted); }
|
||||
/* Distinguish stderr lines (orange) and operator-initiated notes
|
||||
|
|
|
|||
Loading…
Reference in a new issue