Skip to content

Commit 61ac093

Browse files
authored
fix(desktop): leave a stopped native file tool's outcome to Stop (#8732)
A local read or import cancelled by the user's Stop (or by signing out) reported its own failure, which raced Stop's settlement: whichever committed first decided whether the call ended failed or cancelled. Native file tools now report nothing once cancelled, like browser actions and granted-folder reads, so Stop's record stands.
1 parent 96014bd commit 61ac093

2 files changed

Lines changed: 29 additions & 0 deletions

File tree

‎apps/sim/lib/mothership/tools/client/native-files.test.ts‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,28 @@ it('returns local visual observations through the existing completion path', asy
125125
expect(mocks.complete).toHaveBeenCalledWith('tool', 'success', expect.any(String), data)
126126
expect(mocks.upload).not.toHaveBeenCalled()
127127
})
128+
129+
it('an import the user stopped leaves its outcome to Stop instead of reporting a failure', async () => {
130+
const stop = new AbortController()
131+
mocks.invoke.mockResolvedValueOnce({ ok: true, data: manifest })
132+
mocks.upload.mockImplementationOnce(async () => {
133+
stop.abort('user_stop:client_stopGeneration')
134+
throw new DOMException('The operation was aborted.', 'AbortError')
135+
})
136+
await executeNativeFileTool('tool', 'import_local_files', stop.signal)
137+
expect(mocks.complete).not.toHaveBeenCalled()
138+
expect(mocks.exit).not.toHaveBeenCalled()
139+
})
140+
141+
it('a read the user stopped while the desktop was reading reports nothing', async () => {
142+
const stop = new AbortController()
143+
mocks.invoke.mockImplementationOnce(async () => {
144+
stop.abort('user_stop:client_stopGeneration')
145+
return {
146+
ok: true,
147+
data: { kind: 'read', path: '/notes.txt', representation: 'text', text: 'notes' },
148+
}
149+
})
150+
await executeNativeFileTool('tool', 'read_local_file', stop.signal)
151+
expect(mocks.complete).not.toHaveBeenCalled()
152+
})

‎apps/sim/lib/mothership/tools/client/native-files.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ export async function executeNativeFileTool(
145145
response.data.kind === 'manifest'
146146
? localFileImportCompletion(await importNativeFiles(toolCallId, response.data, signal))
147147
: localFileReadCompletion(response)
148+
// Cancelled by the user's Stop or by signing out: whoever cancelled it settles the call, as for
149+
// browser actions and granted-folder reads. A failure reported here would race Stop's record.
150+
if (signal?.aborted) return
148151
await reportClientToolCompletion(
149152
toolCallId,
150153
completion.status,
@@ -153,6 +156,7 @@ export async function executeNativeFileTool(
153156
)
154157
settled = true
155158
} catch (error) {
159+
if (signal?.aborted) return
156160
await reportClientToolCompletion(
157161
toolCallId,
158162
ASYNC_TOOL_CONFIRMATION_STATUS.error,

0 commit comments

Comments
 (0)