Skip to content

Commit cbffe90

Browse files
authored
fix(mothership): strip presentation activity from desktop-authorized tool args (#8277)
* fix(mothership): strip presentation activity before desktop browser dispatch * fix(mothership): strip activity from desktop-authorized tool args
1 parent 4455a54 commit cbffe90

2 files changed

Lines changed: 23 additions & 3 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
})

0 commit comments

Comments
 (0)