fix: keep chat replies out of results

Completed local and channel replies were duplicated into Results as Markdown artifacts, making the panel a second conversation history. Replies now stay in their conversations, legacy duplicates are filtered without deleting data, and standalone images, scheduled jobs, headless delegations, heartbeats, and imports remain visible.

Release note: 普通本地与消息通道回复不再重复出现在成果栏;已有重复内容仅从列表隐藏,不会删除历史数据。
This commit is contained in:
mesalogo
2026-08-18 13:14:13 +08:00
parent e387c09f52
commit 0413807b8f
10 changed files with 173 additions and 84 deletions
+42 -2
View File
@@ -6640,9 +6640,9 @@ describe('App', () => {
screen.getByText(/Agent 打开网页后/)
).toBeInTheDocument()
fireEvent.click(screen.getByRole('tab', { name: '成果' }))
expect(screen.getByText('对话与导入成果')).toBeInTheDocument()
expect(screen.getByText('生成与导入成果')).toBeInTheDocument()
expect(
screen.getByText(/查看并预览由对话生成或手动导入/)
screen.getByText(/查看并预览由任务、自动化生成或手动导入/)
).toBeInTheDocument()
expect(
screen.queryByRole('tab', { name: '预览' })
@@ -6651,6 +6651,46 @@ describe('App', () => {
expect(sidebar).not.toHaveClass('assistant-sidebar--open')
})
it('keeps completed chat replies out of the results sidebar', async () => {
render(<App />)
fireEvent.change(screen.getByLabelText('向 GoodBuddy 提问'), {
target: { value: '普通聊天问题' }
})
fireEvent.click(await screen.findByLabelText('发送'))
await waitFor(() => expect(run).toHaveBeenCalledOnce())
const request = run.mock.calls[0]?.[0]
if (!request) {
throw new Error('Missing request')
}
act(() => {
agentListener?.({
requestId: request.requestId,
type: 'text',
delta: '这是一条普通聊天回复'
})
agentListener?.({
requestId: request.requestId,
type: 'done'
})
})
expect(
await screen.findByText('这是一条普通聊天回复')
).toBeInTheDocument()
fireEvent.click(screen.getByLabelText('切换助手工作栏'))
fireEvent.click(screen.getByRole('tab', { name: '成果' }))
const sidebar = screen.getByLabelText('助手工作栏')
expect(
within(sidebar).queryByText('这是一条普通聊天回复')
).not.toBeInTheDocument()
expect(
within(sidebar).getByText(
'生成的文件、图片、报告和手动导入内容会显示在这里。'
)
).toBeInTheDocument()
})
it('opens the live browser tab for the active conversation and can stop it', async () => {
render(<App />)
+4 -29
View File
@@ -2958,8 +2958,8 @@ function App(): React.JSX.Element {
[conversations]
)
const sidebarArtifacts = useMemo<SidebarArtifact[]>(
() => {
const persisted = assistantArtifacts
() =>
assistantArtifacts
.filter(
(artifact) =>
!activeProjectId || artifact.projectId === activeProjectId
@@ -2970,33 +2970,8 @@ function App(): React.JSX.Element {
content: artifact.content ?? '',
createdAt: new Date(artifact.createdAt).getTime(),
mimeType: artifact.mimeType
}))
if (persisted.length > 0) {
return persisted
}
return (activeConversation?.messages ?? [])
.filter(
(message) =>
message.role === 'assistant' &&
message.state === 'complete' &&
message.content.trim()
)
.slice(-20)
.reverse()
.map((message, index) => ({
id: message.id,
title:
message.content
.split(/\r?\n/, 1)[0]
?.replace(/^#+\s*/, '')
.slice(0, 48) ||
t('chat.assistantResult', { index: index + 1 }),
content: message.content,
createdAt: message.createdAt,
mimeType: 'text/markdown'
}))
},
[activeConversation, activeProjectId, assistantArtifacts, t]
})),
[activeProjectId, assistantArtifacts]
)
const enabledSidebarLibraries = useMemo(
() =>
@@ -135,7 +135,6 @@ export const app = {
},
chat: {
user: 'You',
assistantResult: 'Assistant result {{index}}',
welcome: {
eyebrow: 'GOODBUDDY WORKSPACE',
title: 'What would you like to accomplish today?',
@@ -87,7 +87,7 @@ export const workspace = {
},
results: {
label: 'Results',
description: 'View generated or imported content'
description: 'View generated or imported standalone results'
}
},
tasks: {
@@ -151,10 +151,11 @@ export const workspace = {
title: 'Results',
loadingImage: 'Loading image…',
description:
'View and preview text, images, PDFs, and web content generated by conversations or imported manually.',
sectionTitle: 'Conversation and imported results',
'View and preview text, images, PDFs, and web results generated by tasks or automations, or imported manually.',
sectionTitle: 'Generated and imported results',
import: 'Import PDF, image, or web page',
empty: 'Completed responses will appear here as previewable results.'
empty:
'Generated files, images, reports, and manually imported content will appear here.'
},
browser: {
title: 'Live browser',
@@ -132,7 +132,6 @@ export const app = {
},
chat: {
user: '用户',
assistantResult: '助手成果 {{index}}',
welcome: {
eyebrow: 'GOODBUDDY 工作台',
title: '今天想一起完成什么?',
@@ -83,7 +83,7 @@ export const workspace = {
},
results: {
label: '成果',
description: '查看对话生成或手动导入的内容'
description: '查看生成或手动导入的独立成果'
}
},
tasks: {
@@ -142,10 +142,10 @@ export const workspace = {
title: '成果',
loadingImage: '正在加载图片…',
description:
'查看并预览由对话生成或手动导入的文本、图片、PDF 与网页内容。',
sectionTitle: '对话与导入成果',
'查看并预览由任务、自动化生成或手动导入的文本、图片、PDF 与网页成果。',
sectionTitle: '生成与导入成果',
import: '导入 PDF、图片或网页',
empty: '完成的回复会作为可预览成果显示在这里。'
empty: '生成的文件、图片、报告和手动导入内容会显示在这里。'
},
browser: {
title: '实时浏览器',