From 5430a44561884c243ed38f167da0d0b154002a80 Mon Sep 17 00:00:00 2001 From: Federico Jaramillo Martinez Date: Thu, 7 May 2026 14:23:40 +0200 Subject: [PATCH] Improve shell output rendering --- src/client/src/chatMessages.ts | 3 +-- src/client/src/components/ChatView.ts | 7 ++++--- src/client/src/components/shared.ts | 1 + src/client/src/shellMessages.ts | 10 ++++++++-- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/client/src/chatMessages.ts b/src/client/src/chatMessages.ts index 3e57ce7..e46da10 100644 --- a/src/client/src/chatMessages.ts +++ b/src/client/src/chatMessages.ts @@ -31,13 +31,12 @@ function normalizeMessage(message: any): ChatLine[] { } function normalizeBashExecution(message: any): ChatLine { - const lines = [`$ ${message.command ?? ""}`]; + const lines = message.excludeFromContext ? ["excluded from context", "", `$ ${message.command ?? ""}`] : [`$ ${message.command ?? ""}`]; if (message.output) lines.push("", String(message.output)); if (message.exitCode != null) lines.push("", `exit ${message.exitCode}`); if (message.cancelled) lines.push("", "cancelled"); if (message.truncated) lines.push("", "output truncated"); if (message.fullOutputPath) lines.push("", `full output: ${message.fullOutputPath}`); - if (message.excludeFromContext) lines.push("", "excluded from context"); return { role: "bash", parts: [{ type: "text", text: lines.join("\n") }] }; } diff --git a/src/client/src/components/ChatView.ts b/src/client/src/components/ChatView.ts index f8267b7..2e287ca 100644 --- a/src/client/src/components/ChatView.ts +++ b/src/client/src/components/ChatView.ts @@ -44,7 +44,7 @@ export class ChatView extends LitElement { return html`
${message.role} - ${message.parts.map((part) => this.renderPart(part))} + ${message.parts.map((part) => this.renderPart(part, message))}
`; } @@ -61,7 +61,7 @@ export class ChatView extends LitElement { ${messages.map((message) => html`
${message.role} - ${message.parts.map((part) => this.renderPart(part))} + ${message.parts.map((part) => this.renderPart(part, message))}
`)} @@ -69,7 +69,8 @@ export class ChatView extends LitElement { `; } - private renderPart(part: ChatPart) { + private renderPart(part: ChatPart, message?: ChatLine) { + if (part.type === "text" && message?.role === "bash") return html`
${part.text}
`; if (part.type === "text") return html``; if (part.type === "thinking") return html`
thinking
`; if (part.type === "toolCall") return html`
▶ ${part.toolName}${part.summary}
`; diff --git a/src/client/src/components/shared.ts b/src/client/src/components/shared.ts index 3751cd0..d44a6ff 100644 --- a/src/client/src/components/shared.ts +++ b/src/client/src/components/shared.ts @@ -72,6 +72,7 @@ export const chatStyles = css` .part:is(details) { border-top: 1px solid #30363d; padding-top: 8px; } summary { cursor: pointer; color: #8b949e; } pre { margin: 6px 0 0; white-space: pre-wrap; overflow-wrap: anywhere; font: inherit; } + .shell-output { color: #e6edf3; font: 13px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; line-height: 1.45; } `; export const formattedTextStyles = css` diff --git a/src/client/src/shellMessages.ts b/src/client/src/shellMessages.ts index 0455adf..88f0963 100644 --- a/src/client/src/shellMessages.ts +++ b/src/client/src/shellMessages.ts @@ -3,14 +3,14 @@ import type { ChatLine } from "./components/shared"; import type { SessionUiEvent } from "./sessionSocket"; export function shellStartMessage(command: string, excludeFromContext?: boolean): ChatLine { - return textMessage("bash", `$ ${command}${excludeFromContext ? "\n\nexcluded from context" : ""}`); + return textMessage("bash", `${excludeFromContext ? "excluded from context\n\n" : ""}$ ${command}`); } export function appendShellChunk(messages: ChatLine[], chunk: string): ChatLine[] { const last = messages.at(-1); const lastPart = last?.parts.at(-1); if (last?.role !== "bash" || lastPart?.type !== "text") return [...messages, textMessage("bash", chunk)]; - const separator = lastPart.text.includes("\n\n") ? "" : "\n\n"; + const separator = hasShellOutput(lastPart.text) ? "" : "\n\n"; return [...messages.slice(0, -1), { ...last, parts: [...last.parts.slice(0, -1), { ...lastPart, text: lastPart.text + separator + chunk }] }]; } @@ -28,3 +28,9 @@ export function finalizeShellMessage(messages: ChatLine[], event: Extract promptStart; +}