Skip to content

Commit 25fb5e4

Browse files
committed
fix(mothership): strip activity from desktop-authorized tool args
1 parent 5169122 commit 25fb5e4

4 files changed

Lines changed: 25 additions & 28 deletions

File tree

‎apps/sim/app/api/desktop/tool/authorize/route.test.ts‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,25 @@ describe('desktop tool authorization', () => {
8787
expect(claimPendingAsyncToolCall).toHaveBeenCalledWith('browser-tool', 'desktop-browser')
8888
})
8989

90+
it('never returns presentation activity as an executable browser argument', async () => {
91+
const fields = [{ elementId: 1, kind: 'text', text: 'a' }]
92+
getAsyncToolCall.mockResolvedValueOnce({
93+
toolCallId: 'form-tool',
94+
runId: 'run-1',
95+
status: 'pending',
96+
toolName: 'browser_fill_form',
97+
args: { activity: { description: 'Filling the form' }, fields },
98+
})
99+
100+
const response = await POST(request('form-tool'))
101+
expect(response.status).toBe(200)
102+
expect(await response.json()).toEqual({
103+
chatId: 'chat-1',
104+
toolName: 'browser_fill_form',
105+
args: { fields },
106+
})
107+
})
108+
90109
it('rejects retired browser tools retained only for history', async () => {
91110
getAsyncToolCall.mockResolvedValueOnce({
92111
toolCallId: 'retired-browser-tool',

‎apps/sim/app/api/desktop/tool/authorize/route.ts‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { isCurrentBrowserToolName } from '@sim/browser-protocol'
22
import { isTerminalToolName } from '@sim/terminal-protocol'
3-
import { isRecordLike } from '@sim/utils/object'
3+
import { isRecordLike, omit } from '@sim/utils/object'
44
import { type NextRequest, NextResponse } from 'next/server'
55
import { authorizeDesktopToolContract } from '@/lib/api/contracts/desktop-tool-authorization'
66
import { parseRequest } from '@/lib/api/server'
@@ -24,7 +24,8 @@ import { isUserLocalVfsToolCall } from '@/lib/mothership/tools/local-filesystem'
2424
* Electron calls this endpoint from the main process before every privileged
2525
* native model action. It returns only server-persisted canonical tool args;
2626
* Electron validates local-file requests against them and uses them directly
27-
* for browser and terminal tools.
27+
* for browser and terminal tools. The presentation-only `activity` field is
28+
* dropped: desktop actions reject arguments they do not declare.
2829
*/
2930
export const POST = withRouteHandler(async (request: NextRequest) => {
3031
const { userId, isAuthenticated } = await authenticateCopilotRequestSessionOnly()
@@ -117,7 +118,7 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
117118

118119
return NextResponse.json({
119120
toolName: toolCall.toolName,
120-
args,
121+
args: omit(args, ['activity']),
121122
chatId: run.chatId,
122123
})
123124
})

‎apps/sim/lib/mothership/tools/client/browser-tool-execution.test.ts‎

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -110,27 +110,6 @@ describe('executeBrowserToolOnClient', () => {
110110
expect(mockExecuteBrowserTool).toHaveBeenCalledTimes(1)
111111
})
112112

113-
it('never forwards presentation activity to the desktop driver', async () => {
114-
mockExecuteBrowserTool.mockResolvedValue({ completed: true, results: [] })
115-
const toolCallId = nextToolCallId()
116-
const fields = [{ elementId: 1, kind: 'text', text: 'a' }]
117-
executeBrowserToolOnClient(
118-
toolCallId,
119-
'browser_fill_form',
120-
{ activity: { description: 'Filling the form' }, fields },
121-
CHAT_SCOPE
122-
)
123-
await flush()
124-
expect(mockExecuteBrowserTool).toHaveBeenCalledWith(
125-
toolCallId,
126-
'browser_fill_form',
127-
{ fields },
128-
expect.anything(),
129-
CHAT_SCOPE,
130-
expect.any(Function)
131-
)
132-
})
133-
134113
it('reports a batch as failed only when one of its actions failed', async () => {
135114
const actions = [
136115
{ tool: 'browser_click', args: { elementId: 1 } },

‎apps/sim/lib/mothership/tools/client/browser-tool-execution.ts‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -898,16 +898,14 @@ async function doExecuteBrowserTool(
898898

899899
logger.info('Executing browser tool via the desktop agent browser', { toolCallId, toolName })
900900

901-
/** `activity` is presentation metadata for the chat row; desktop actions reject unknown keys. */
902-
const { activity: _activity, ...actionParams } = params
903901
let result: unknown
904902
try {
905903
nativeDispatchStarted = true
906904
result = await executeBrowserTool(
907905
toolCallId,
908906
toolName,
909-
actionParams,
910-
timeoutForTool(toolName, actionParams),
907+
params,
908+
timeoutForTool(toolName, params),
911909
scopeId,
912910
() => {
913911
cancelled = true

0 commit comments

Comments
 (0)