fix: hide blank assistant message bubbles

This commit is contained in:
Relakkes Yang 2026-05-01 22:09:55 +08:00
parent 74766d8880
commit 465e043563
5 changed files with 72 additions and 1 deletions

View File

@ -8,6 +8,8 @@ type Props = {
}
export function AssistantMessage({ content, isStreaming }: Props) {
if (!content.trim()) return null
const documentLayout = shouldUseDocumentLayout(content)
return (

View File

@ -95,6 +95,41 @@ describe('MessageList nested tool calls', () => {
expect(container.textContent).toContain('Agent')
})
it('does not render blank assistant bubbles for whitespace-only text', () => {
const messages: UIMessage[] = [
{
id: 'assistant-empty',
type: 'assistant_text',
content: '\n\n ',
timestamp: 1,
},
{
id: 'tool-bash',
type: 'tool_use',
toolName: 'Bash',
toolUseId: 'bash-1',
input: { command: 'pwd' },
timestamp: 2,
},
]
const { renderItems } = buildRenderModel(messages)
expect(renderItems).toHaveLength(1)
expect(renderItems[0]).toMatchObject({ kind: 'tool_group' })
useChatStore.setState({
sessions: {
[ACTIVE_TAB]: makeSessionState({
messages,
streamingText: '\n ',
}),
},
})
const { container } = render(<MessageList />)
expect(container.querySelectorAll('[data-message-shell="assistant"]')).toHaveLength(0)
})
it('keeps root tool runs split when nested child tool calls appear between them', () => {
const messages: UIMessage[] = [
{

View File

@ -90,6 +90,10 @@ export function buildRenderModel(messages: UIMessage[]): RenderModel {
}
for (const msg of messages) {
if (msg.type === 'assistant_text' && !msg.content.trim()) {
continue
}
if (msg.type === 'tool_result' && toolUseIds.has(msg.toolUseId)) {
continue
}
@ -495,7 +499,7 @@ export function MessageList({ sessionId, compact = false }: MessageListProps = {
)
})}
{streamingText && (
{streamingText.trim() && (
<AssistantMessage content={streamingText} isStreaming={chatState === 'streaming'} />
)}

View File

@ -184,6 +184,35 @@ describe('chatStore history mapping', () => {
])
})
it('skips whitespace-only assistant transcript messages', () => {
const messages: MessageEntry[] = [
{
id: 'assistant-empty',
type: 'assistant',
timestamp: '2026-04-06T00:00:00.000Z',
model: 'opus',
content: '\n\n ',
},
{
id: 'assistant-real',
type: 'assistant',
timestamp: '2026-04-06T00:00:01.000Z',
model: 'opus',
content: '可见回复',
},
]
const mapped = mapHistoryMessagesToUiMessages(messages)
expect(mapped).toMatchObject([
{
id: 'assistant-real',
type: 'assistant_text',
content: '可见回复',
},
])
})
it('surfaces teammate prompt content when mapping member transcript history', () => {
const messages: MessageEntry[] = [
{

View File

@ -1080,6 +1080,7 @@ export function mapHistoryMessagesToUiMessages(
continue
}
if (msg.type === 'assistant' && typeof msg.content === 'string') {
if (!msg.content.trim()) continue
uiMessages.push({ id: msg.id || nextId(), type: 'assistant_text', content: msg.content, timestamp, model: msg.model })
continue
}