fix(ui): hide synthetic helper text in user messages

Avoid rendering tool trace/read output parts on user messages while keeping the primary prompt text visible.
This commit is contained in:
Shantur Rathore
2026-02-14 09:53:40 +00:00
parent 4e0f064c3a
commit 2d93d82611
3 changed files with 29 additions and 5 deletions

View File

@@ -45,6 +45,15 @@ export default function MessageItem(props: MessageItemProps) {
const messageParts = () => props.parts
// User messages can temporarily include synthetic helper parts (e.g. tool traces / file reads).
// We only want to display the primary prompt text for the user message; other synthetic text
// parts should be hidden.
const primaryUserTextPartId = () => {
if (!isUser()) return null
const firstText = messageParts().find((part) => part?.type === "text") as { id?: string } | undefined
return typeof firstText?.id === "string" ? firstText.id : null
}
const fileAttachments = () =>
messageParts().filter((part): part is FilePart => part?.type === "file" && typeof (part as FilePart).url === "string")
@@ -372,6 +381,7 @@ export default function MessageItem(props: MessageItemProps) {
messageType={props.record.role}
instanceId={props.instanceId}
sessionId={props.sessionId}
primaryUserTextPartId={primaryUserTextPartId()}
onRendered={props.onContentRendered}
/>
)}

View File

@@ -13,9 +13,12 @@ interface MessagePartProps {
messageType?: "user" | "assistant"
instanceId: string
sessionId: string
// For user messages, keep the primary prompt text visible even when synthetic (optimistic).
// Other synthetic text parts (tool traces, read outputs, etc.) should be hidden.
primaryUserTextPartId?: string | null
onRendered?: () => void
}
export default function MessagePart(props: MessagePartProps) {
export default function MessagePart(props: MessagePartProps) {
const { isDark } = useTheme()
const { preferences } = useConfig()
@@ -28,8 +31,19 @@ interface MessagePartProps {
const shouldHideTextPart = () => {
const part = props.part
if (!part || part.type !== "text") return false
// Keep optimistic user prompts visible; hide synthetic assistant text.
return Boolean((part as any).synthetic) && props.messageType !== "user"
const isSynthetic = Boolean((part as any).synthetic)
if (!isSynthetic) return false
// Keep optimistic user prompts visible; hide other synthetic user helper parts.
if (props.messageType === "user") {
const primaryId = props.primaryUserTextPartId
if (!primaryId) return false
return part.id !== primaryId
}
// Hide synthetic assistant text.
return true
}

View File

@@ -1,4 +1,4 @@
import type { Attachment } from "../types/attachment"
import type { Attachment, FileSource } from "../types/attachment"
export function resolvePastedPlaceholders(prompt: string, attachments: Attachment[] = []): string {
if (!prompt) {
@@ -12,7 +12,7 @@ export function resolvePastedPlaceholders(prompt: string, attachments: Attachmen
// IMPORTANT: avoid rewriting plain `@mentions` or email addresses.
const fileAttachmentPaths = new Set(
attachments
.filter((a) => a.source.type === "file")
.filter((a): a is Attachment & { source: FileSource } => a.source.type === "file")
.map((a) => a.source.path),
)