diff --git a/agent/memory/conversation_store.py b/agent/memory/conversation_store.py index b620986d..c5d215bf 100644 --- a/agent/memory/conversation_store.py +++ b/agent/memory/conversation_store.py @@ -116,9 +116,10 @@ def _extract_tool_calls(content: Any) -> List[Dict[str, Any]]: ] -def _extract_tool_results(content: Any) -> Dict[str, str]: +def _extract_tool_results(content: Any) -> Dict[str, dict]: """ Extract tool_result blocks from a user message, keyed by tool_use_id. + Values are {"result": str, "is_error": bool}. """ if not isinstance(content, list): return {} @@ -133,7 +134,7 @@ def _extract_tool_results(content: Any) -> Dict[str, str]: rb.get("text", "") for rb in result_content if isinstance(rb, dict) and rb.get("type") == "text" ) - results[tool_id] = str(result_content) + results[tool_id] = {"result": str(result_content), "is_error": bool(b.get("is_error", False))} return results @@ -242,7 +243,11 @@ def _group_into_display_turns( # Attach tool results to tool steps for step in steps: if step["type"] == "tool": - step["result"] = tool_results.get(step.get("id", ""), "") + tr = tool_results.get(step.get("id", ""), {}) + if not isinstance(tr, dict): + tr = {"result": tr} + step["result"] = tr.get("result", "") + step["is_error"] = tr.get("is_error", False) if steps or final_text: turn = { diff --git a/channel/web/static/js/console.js b/channel/web/static/js/console.js index f273c495..fa094664 100644 --- a/channel/web/static/js/console.js +++ b/channel/web/static/js/console.js @@ -1728,10 +1728,14 @@ function renderStepsHtml(steps) { } else if (step.type === 'tool') { const argsStr = formatToolArgs(step.arguments || {}); const resultStr = step.result ? escapeHtml(String(step.result)) : ''; + const isErr = step.is_error === true; + const iconClass = isErr + ? 'fas fa-times text-red-400 flex-shrink-0 tool-icon' + : 'fas fa-check text-primary-400 flex-shrink-0 tool-icon'; html += ` -
${resultStr}
+ ${resultStr}