Skip to content

Commit bb7f068

Browse files
committed
fix(chat): retain answered browser handoffs
1 parent eae212b commit bb7f068

3 files changed

Lines changed: 58 additions & 2 deletions

File tree

apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/agent-group/agent-group.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,46 @@ describe('AgentGroup inline main activity', () => {
160160
expect(container.querySelector('button, svg, [data-state], .pl-6')).toBeNull()
161161
})
162162

163+
it('keeps a browser question and answer after the main agent resumes tool activity', () => {
164+
const takeover = browserTakeover('Choose a result.')
165+
const items: AgentGroupItem[] = [
166+
{
167+
...takeover,
168+
data: {
169+
...takeover.data,
170+
status: 'success',
171+
result: { success: true, output: { userInstruction: 'Open the second result.' } },
172+
},
173+
},
174+
{
175+
type: 'tool',
176+
data: {
177+
id: 'resumed',
178+
toolName: 'grep',
179+
displayTitle: 'Searching files',
180+
status: 'success',
181+
},
182+
},
183+
]
184+
185+
act(() => {
186+
root.render(
187+
createElement(AgentGroup, {
188+
agentName: 'mothership',
189+
agentLabel: 'Sim',
190+
items,
191+
isStreaming: false,
192+
})
193+
)
194+
})
195+
196+
expect(container.querySelector('[data-takeover-answer="true"]')?.textContent).toBe(
197+
'Choose a result.: Open the second result.'
198+
)
199+
expect(container.textContent).toContain('Searched files')
200+
expect(container.querySelector('button, svg, [data-state], .pl-6')).toBeNull()
201+
})
202+
163203
it('keeps pending permissions and terminal handoffs visible when newer tools arrive', () => {
164204
const items: AgentGroupItem[] = [
165205
{

apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/agent-group/main-agent-activity.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Terminal as TerminalTool } from '@/lib/copilot/generated/tool-catalog-v1'
2+
import { RETIRED_BROWSER_REQUEST_TAKEOVER_ID } from '@/lib/copilot/tools/retired-tools'
23
import type { AgentGroupItem } from '@/app/workspace/[workspaceId]/home/components/message-content/components/agent-group/agent-group-view'
34
import { ToolCallStatus } from '@/app/workspace/[workspaceId]/home/types'
45

@@ -9,7 +10,7 @@ export function getLatestToolId(items: AgentGroupItem[]): string | undefined {
910
}
1011
}
1112

12-
/** Keep blocking controls visible even when a newer tool replaces the activity text. */
13+
/** Keep interaction controls and answers when a newer tool replaces the activity text. */
1314
export function getVisibleMainAgentItems(
1415
items: AgentGroupItem[],
1516
latestToolId = getLatestToolId(items)
@@ -19,6 +20,8 @@ export function getVisibleMainAgentItems(
1920
item.type !== 'tool' ||
2021
item.data.id === latestToolId ||
2122
item.data.status === ToolCallStatus.awaiting_approval ||
23+
(item.data.toolName === RETIRED_BROWSER_REQUEST_TAKEOVER_ID &&
24+
item.data.status === ToolCallStatus.success) ||
2225
(item.data.status === ToolCallStatus.executing &&
2326
item.data.toolName === TerminalTool.id &&
2427
item.data.params?.operation === 'handoff')

apps/sim/app/workspace/[workspaceId]/home/components/message-content/message-content.test.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,7 @@ describe('assistantMessageHasVisibleExecutingTool', () => {
846846

847847
describe('parseBlocks main activity controls', () => {
848848
it.each([undefined, 'main'])(
849-
'retains blocking controls across prose and completion with spanId=%s',
849+
'retains interaction controls and answers across prose and completion with spanId=%s',
850850
(spanId) => {
851851
const blocks: ContentBlock[] = [
852852
{
@@ -866,6 +866,17 @@ describe('parseBlocks main activity controls', () => {
866866
},
867867
timestamp: 2,
868868
},
869+
{
870+
type: 'tool_call',
871+
toolCall: {
872+
id: 'answered-takeover',
873+
name: 'browser_request_takeover',
874+
status: 'success',
875+
params: { reason: 'Choose a result.' },
876+
result: { success: true, output: { userInstruction: 'Open the second result.' } },
877+
},
878+
timestamp: 2,
879+
},
869880
mainToolCall('older', 'grep'),
870881
mainText('Checking another source.'),
871882
{
@@ -885,6 +896,7 @@ describe('parseBlocks main activity controls', () => {
885896
expect(visibleTools(blocks).map((tool) => tool.id)).toEqual([
886897
'permission',
887898
'handoff',
899+
'answered-takeover',
888900
'latest',
889901
])
890902
const completed = blocks.map((block) =>
@@ -895,6 +907,7 @@ describe('parseBlocks main activity controls', () => {
895907
expect(visibleTools(completed).map((tool) => tool.id)).toEqual([
896908
'permission',
897909
'handoff',
910+
'answered-takeover',
898911
'latest',
899912
])
900913
expect(visibleTools(completed).at(-1)?.status).toBe('success')

0 commit comments

Comments
 (0)