@@ -326,44 +326,65 @@ describe('sse-handlers tool lifecycle', () => {
326326 )
327327 } )
328328
329- it ( 'pre-persists browser tools as pending for the desktop authorization claim' , async ( ) => {
330- isSimExecuted . mockReturnValue ( false )
331- context . runId = 'run-1'
332-
333- await prePersistClientExecutableToolCall (
334- {
335- type : MothershipStreamV1EventType . tool ,
336- payload : {
337- toolCallId : 'browser-tool-1' ,
338- toolName : 'browser_list_tabs' ,
339- arguments : { } ,
340- executor : MothershipStreamV1ToolExecutor . client ,
341- mode : MothershipStreamV1ToolMode . async ,
342- phase : MothershipStreamV1ToolPhase . call ,
343- } ,
344- } satisfies StreamEvent ,
345- context ,
346- { } ,
347- execContext
348- )
349-
350- expect ( upsertAsyncToolCall ) . toHaveBeenCalledWith ( {
351- runId : 'run-1' ,
352- toolCallId : 'browser-tool-1' ,
353- toolName : 'browser_list_tabs' ,
354- args : { } ,
355- sealedContext : { __sealedClientToolContextV1 : 'sealed-context' } ,
356- status : MothershipStreamV1AsyncToolRecordStatus . pending ,
357- permissionRequested : false ,
358- } )
359- expect ( sealClientToolContext ) . toHaveBeenCalledWith ( {
360- toolCallId : 'browser-tool-1' ,
361- runId : 'run-1' ,
362- userId : 'user-1' ,
363- registry : execContext . resolvedSecretTraceRegistry ,
364- toolInput : { } ,
365- } )
366- } )
329+ describe . each ( [ 'browser_list_tabs' , 'terminal' , 'import_local_files' , 'computer' ] ) (
330+ 'native %s pre-persistence' ,
331+ ( toolName ) => {
332+ it . each ( [ false , true ] ) (
333+ 'keeps the call pending for the desktop claim when approval gating is %s' ,
334+ async ( gated ) => {
335+ isSimExecuted . mockReturnValue ( false )
336+ toolRequiresApproval . mockReturnValue ( gated )
337+ context . runId = 'run-1'
338+ context . toolPermissions . enabled = gated
339+ const args =
340+ toolName === 'computer'
341+ ? { action : 'status' }
342+ : toolName === 'terminal'
343+ ? { operation : 'run' , command : 'pwd' }
344+ : { }
345+ const event = {
346+ type : MothershipStreamV1EventType . tool ,
347+ payload : {
348+ toolCallId : 'native-tool-1' ,
349+ toolName,
350+ arguments : args ,
351+ executor : MothershipStreamV1ToolExecutor . client ,
352+ mode : MothershipStreamV1ToolMode . async ,
353+ phase : MothershipStreamV1ToolPhase . call ,
354+ } ,
355+ } satisfies StreamEvent
356+
357+ await prePersistClientExecutableToolCall ( event , context , { } , execContext )
358+
359+ expect ( upsertAsyncToolCall ) . toHaveBeenCalledExactlyOnceWith ( {
360+ runId : 'run-1' ,
361+ toolCallId : 'native-tool-1' ,
362+ toolName,
363+ args,
364+ sealedContext : { __sealedClientToolContextV1 : 'sealed-context' } ,
365+ status : MothershipStreamV1AsyncToolRecordStatus . pending ,
366+ permissionRequested : gated ,
367+ } )
368+ expect ( sealClientToolContext ) . toHaveBeenCalledWith ( {
369+ toolCallId : 'native-tool-1' ,
370+ runId : 'run-1' ,
371+ userId : 'user-1' ,
372+ registry : execContext . resolvedSecretTraceRegistry ,
373+ toolInput : args ,
374+ } )
375+ expect ( event . payload ) . toEqual ( {
376+ toolCallId : 'native-tool-1' ,
377+ toolName,
378+ arguments : args ,
379+ executor : MothershipStreamV1ToolExecutor . client ,
380+ mode : MothershipStreamV1ToolMode . async ,
381+ phase : MothershipStreamV1ToolPhase . call ,
382+ ...( gated ? { status : 'awaiting_approval' } : { } ) ,
383+ } )
384+ }
385+ )
386+ }
387+ )
367388
368389 it ( 'persists a gated sim tool and stamps the frame so a reload can still answer it' , async ( ) => {
369390 toolRequiresApproval . mockReturnValue ( true )
0 commit comments