@@ -211,6 +211,87 @@ describe('ToolExecutor', () => {
211211 } ) ;
212212 } ) ;
213213
214+ it ( 'should return cancelled result when executeToolWithHooks rejects with AbortError' , async ( ) => {
215+ const mockTool = new MockTool ( {
216+ name : 'webSearchTool' ,
217+ description : 'Mock web search' ,
218+ } ) ;
219+ const invocation = mockTool . build ( { } ) ;
220+
221+ const abortErr = new Error ( 'The user aborted a request.' ) ;
222+ abortErr . name = 'AbortError' ;
223+ vi . mocked ( coreToolHookTriggers . executeToolWithHooks ) . mockRejectedValue (
224+ abortErr ,
225+ ) ;
226+
227+ const scheduledCall : ScheduledToolCall = {
228+ status : CoreToolCallStatus . Scheduled ,
229+ request : {
230+ callId : 'call-abort' ,
231+ name : 'webSearchTool' ,
232+ args : { } ,
233+ isClientInitiated : false ,
234+ prompt_id : 'prompt-abort' ,
235+ } ,
236+ tool : mockTool ,
237+ invocation : invocation as unknown as AnyToolInvocation ,
238+ startTime : Date . now ( ) ,
239+ } ;
240+
241+ const result = await executor . execute ( {
242+ call : scheduledCall ,
243+ signal : new AbortController ( ) . signal ,
244+ onUpdateToolCall : vi . fn ( ) ,
245+ } ) ;
246+
247+ expect ( result . status ) . toBe ( CoreToolCallStatus . Cancelled ) ;
248+ if ( result . status === CoreToolCallStatus . Cancelled ) {
249+ const response = result . response . responseParts [ 0 ] ?. functionResponse
250+ ?. response as Record < string , unknown > ;
251+ expect ( response [ 'error' ] ) . toContain ( 'Operation cancelled.' ) ;
252+ }
253+ } ) ;
254+
255+ it ( 'should return cancelled result when executeToolWithHooks rejects with "Operation cancelled by user" message' , async ( ) => {
256+ const mockTool = new MockTool ( {
257+ name : 'someTool' ,
258+ description : 'Mock' ,
259+ } ) ;
260+ const invocation = mockTool . build ( { } ) ;
261+
262+ const cancelErr = new Error ( 'Operation cancelled by user' ) ;
263+ vi . mocked ( coreToolHookTriggers . executeToolWithHooks ) . mockRejectedValue (
264+ cancelErr ,
265+ ) ;
266+
267+ const scheduledCall : ScheduledToolCall = {
268+ status : CoreToolCallStatus . Scheduled ,
269+ request : {
270+ callId : 'call-cancel-msg' ,
271+ name : 'someTool' ,
272+ args : { } ,
273+ isClientInitiated : false ,
274+ prompt_id : 'prompt-cancel-msg' ,
275+ } ,
276+ tool : mockTool ,
277+ invocation : invocation as unknown as AnyToolInvocation ,
278+ startTime : Date . now ( ) ,
279+ } ;
280+
281+ const result = await executor . execute ( {
282+ call : scheduledCall ,
283+ signal : new AbortController ( ) . signal ,
284+ onUpdateToolCall : vi . fn ( ) ,
285+ } ) ;
286+
287+ expect ( result . status ) . toBe ( CoreToolCallStatus . Cancelled ) ;
288+ if ( result . status === CoreToolCallStatus . Cancelled ) {
289+ const response = result . response . responseParts [ 0 ] ?. functionResponse
290+ ?. response as Record < string , unknown > ;
291+ expect ( response [ 'error' ] ) . toContain ( 'User cancelled tool execution.' ) ;
292+ }
293+ } ) ;
294+
214295 it ( 'should return cancelled result when signal is aborted' , async ( ) => {
215296 const mockTool = new MockTool ( {
216297 name : 'slowTool' ,
0 commit comments