Skip to content

Commit 594894c

Browse files
authored
fix(chat): keep empty search activity collapsed (#8477)
1 parent 0f218b6 commit 594894c

4 files changed

Lines changed: 59 additions & 58 deletions

File tree

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { collectRetrievalCitationEvidence } from '@/lib/mothership/chat/citation-evidence'
2+
import type { SourceTagData } from '@/app/workspace/[workspaceId]/home/components/message-content/components/special-tags'
3+
import { indexSourcesByUrl } from '@/app/workspace/[workspaceId]/home/components/message-content/sources-by-url'
4+
import type { ToolCallData } from '@/app/workspace/[workspaceId]/home/types'
5+
6+
/** Only searches with safe sources have displayable details. */
7+
export function getSearchActivitySources(tool: ToolCallData): SourceTagData[] | undefined {
8+
if (tool.toolName !== 'search_workspace') return undefined
9+
const evidence = collectRetrievalCitationEvidence([
10+
{ toolCall: { name: tool.toolName, status: tool.status, result: tool.result } },
11+
])
12+
const sources = [...indexSourcesByUrl(evidence.values()).values()]
13+
return sources.length > 0 ? sources : undefined
14+
}

‎apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/agent-group/search-activity-details.tsx‎

Lines changed: 0 additions & 43 deletions
This file was deleted.

‎apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/agent-group/tool-activity-group.test.tsx‎

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44
import { act } from 'react'
55
import { createRoot, type Root } from 'react-dom/client'
6-
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
6+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
77
import { ActivityStatus } from '@/components/ui/activity-status'
88
import { ToolActivityGroup } from '@/app/workspace/[workspaceId]/home/components/message-content/components/agent-group/tool-activity-group'
99
import type { ToolCallItemProps } from '@/app/workspace/[workspaceId]/home/components/message-content/components/agent-group/tool-call-item'
@@ -46,6 +46,8 @@ describe('ToolActivityGroup search disclosure', () => {
4646
let root: Root
4747

4848
beforeEach(() => {
49+
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true)
50+
vi.useFakeTimers()
4951
container = document.createElement('div')
5052
document.body.append(container)
5153
root = createRoot(container)
@@ -54,12 +56,13 @@ describe('ToolActivityGroup search disclosure', () => {
5456
afterEach(() => {
5557
act(() => root.unmount())
5658
container.remove()
59+
vi.useRealTimers()
5760
})
5861

59-
function render(tool: ToolCallData, isLive: boolean) {
62+
function render(tools: ToolCallData[], isLive: boolean) {
6063
act(() =>
6164
root.render(
62-
<ToolActivityGroup tools={[tool]} isLive={isLive} ToolCallComponent={TestToolCall} />
65+
<ToolActivityGroup tools={tools} isLive={isLive} ToolCallComponent={TestToolCall} />
6366
)
6467
)
6568
}
@@ -71,26 +74,55 @@ describe('ToolActivityGroup search disclosure', () => {
7174
}
7275

7376
it('opens when live results arrive, closes for the answer, and respects manual choices', () => {
74-
render(executingSearch, true)
77+
render([executingSearch], true)
7578
expect(container.querySelector('[role="button"][aria-expanded]')).toBeNull()
7679

77-
render(completedSearch, true)
80+
render([completedSearch], true)
7881
expect(disclosure().getAttribute('aria-expanded')).toBe('true')
7982
expect(container.querySelector('a[href="https://example.test/guide"]')).not.toBeNull()
8083

81-
render(completedSearch, false)
84+
render([completedSearch], false)
8285
expect(disclosure().getAttribute('aria-expanded')).toBe('false')
8386

8487
act(() => disclosure().click())
8588
expect(disclosure().getAttribute('aria-expanded')).toBe('true')
86-
render(completedSearch, false)
89+
render([completedSearch], false)
8790
expect(disclosure().getAttribute('aria-expanded')).toBe('true')
88-
render(completedSearch, true)
91+
render([completedSearch], true)
8992
expect(disclosure().getAttribute('aria-expanded')).toBe('true')
9093

9194
act(() => disclosure().click())
92-
render(completedSearch, false)
93-
render(completedSearch, true)
95+
render([completedSearch], false)
96+
render([completedSearch], true)
9497
expect(disclosure().getAttribute('aria-expanded')).toBe('false')
9598
})
99+
100+
it('keeps empty searches out of the disclosure while subsequent tools run', () => {
101+
const emptySearch: ToolCallData = {
102+
...completedSearch,
103+
id: 'empty-search',
104+
result: { success: true, output: { success: true, data: { results: [] } } },
105+
}
106+
const runningRead: ToolCallData = {
107+
id: 'read-1',
108+
toolName: 'read_document',
109+
displayTitle: 'Reading document',
110+
status: 'executing',
111+
}
112+
113+
render([emptySearch], true)
114+
expect.soft(container.querySelector('[role="button"][aria-expanded]')).toBeNull()
115+
116+
render([emptySearch, runningRead], true)
117+
expect.soft(disclosure().getAttribute('aria-expanded')).toBe('false')
118+
119+
if (disclosure().getAttribute('aria-expanded') === 'false') {
120+
act(() => disclosure().click())
121+
}
122+
expect.soft(container.textContent).not.toContain('No results')
123+
124+
render([emptySearch, completedSearch], true)
125+
expect(container.querySelector('a[href="https://example.test/guide"]')).not.toBeNull()
126+
expect(container.textContent).not.toContain('No results')
127+
})
96128
})

‎apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/agent-group/tool-activity-group.tsx‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@ import {
1616
import { getToolStatusDisplayTitle } from '@/lib/mothership/tools/tool-display'
1717
import { ActivityStream } from '@/app/workspace/[workspaceId]/home/components/message-content/components/agent-group/activity-stream'
1818
import { getNewestRunningTool } from '@/app/workspace/[workspaceId]/home/components/message-content/components/agent-group/agent-group-content'
19-
import {
20-
getSearchActivitySources,
21-
SearchActivityDetails,
22-
} from '@/app/workspace/[workspaceId]/home/components/message-content/components/agent-group/search-activity-details'
19+
import { getSearchActivitySources } from '@/app/workspace/[workspaceId]/home/components/message-content/components/agent-group/search-activity-details'
20+
import { SearchActivityResults } from '@/app/workspace/[workspaceId]/home/components/message-content/components/agent-group/search-activity-results'
2321
import type { ToolCallItemProps } from '@/app/workspace/[workspaceId]/home/components/message-content/components/agent-group/tool-call-item'
2422
import {
2523
getActivityAttentionKey,
@@ -276,7 +274,7 @@ export function ToolActivityGroup({
276274
<ToolCallComponent {...tool} toolCallId={tool.id} />
277275
)}
278276
{sources && (
279-
<SearchActivityDetails
277+
<SearchActivityResults
280278
sources={sources}
281279
label={`Search results for step ${index + 1}: ${getToolTitle(tool)}`}
282280
/>

0 commit comments

Comments
 (0)