fix(ui): render text-block tool results

This commit is contained in:
Peter Steinberger
2026-05-04 04:25:49 +01:00
parent 6f8b9bb573
commit a4df85e55f
4 changed files with 51 additions and 1 deletions

View File

@@ -47,6 +47,7 @@ Docs: https://docs.openclaw.ai
- Control UI: point the Appearance tweakcn browse action and docs at the live tweakcn editor route instead of the removed `/themes` page. Fixes #77048.
- Control UI: render Dream Diary prose through the sanitized markdown pipeline, so diary bold/italic/header markdown no longer appears as literal source text. Fixes #62413.
- Control UI: render tool results whose output arrives as text-block arrays and give expanded tool output a scrollable block, so read/exec output remains visible in WebChat. Fixes #77054.
- Diagnostics: keep webhook/message OTEL attributes and Prometheus delivery labels low-cardinality and omit raw chat/message IDs from spans, so progress-draft and message-tool modes do not leak high-cardinality messaging identifiers.
- Google Meet: stop advertising legacy `mode: "realtime"` to agents and config UIs, while keeping it as a hidden compatibility alias for `mode: "agent"`, so new joins use the STT -> OpenClaw agent -> TTS path instead of selecting the direct realtime voice fallback.
- Google Meet: add `chrome.audioBufferBytes` for generated command-pair SoX audio commands and lower the default buffer from SoX's 8192 bytes to 4096 bytes to reduce Chrome talk-back latency.

View File

@@ -361,7 +361,15 @@
.chat-tool-card__block-content {
color: var(--text);
overflow-x: auto;
overflow: auto;
max-height: min(520px, 60vh);
}
.chat-tool-card__inline {
margin-top: 10px;
white-space: pre-wrap;
overflow-wrap: anywhere;
word-break: break-word;
}
.chat-tool-card__block-preview {

View File

@@ -136,6 +136,35 @@ describe("tool-card extraction", () => {
});
});
it("extracts tool result output from text block content arrays", () => {
const cards = extractToolCards(
{
role: "assistant",
content: [
{
type: "toolcall",
id: "call-read",
name: "read",
input: { path: "README.md" },
},
{
type: "tool_result",
id: "call-read",
name: "read",
content: [
{ type: "text", text: "# Heading" },
{ type: "text", text: "file body" },
],
},
],
},
"msg:read",
);
expect(cards).toHaveLength(1);
expect(cards[0]?.outputText).toBe("# Heading\nfile body");
});
it("builds sidebar content with input and empty output status", () => {
const [card] = extractToolCards(
{

View File

@@ -48,6 +48,18 @@ function extractToolText(item: Record<string, unknown>): string | undefined {
if (typeof item.content === "string") {
return item.content;
}
if (Array.isArray(item.content)) {
const parts = item.content.flatMap((entry) => {
if (!entry || typeof entry !== "object") {
return [];
}
const text = (entry as { text?: unknown }).text;
return typeof text === "string" ? [text] : [];
});
if (parts.length > 0) {
return parts.join("\n");
}
}
return undefined;
}