@@ -908,7 +908,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
908908 )
909909 const cleanArgs = clean [ shellName ] ?. args ?? clean [ "" ] . args
910910 const rawArgs = invocations [ shellName ] ?. args ?? invocations [ "" ] . args
911- const raw = { file : sh , args : rawArgs }
911+ const raw = { file : sh , args : sandbox . active ? cleanArgs : rawArgs }
912912 const call =
913913 sandbox . active && sandbox . profile
914914 ? SandboxSpawn . wrap ( { profile : sandbox . profile , file : sh , args : cleanArgs } )
@@ -949,16 +949,24 @@ NOTE: At any point in time through this workflow you should feel free to ask the
949949 } ) ,
950950 ) ,
951951 )
952- return yield * handle . exitCode
953- } ) . pipe (
954- Effect . scoped ,
955- Effect . onInterrupt ( ( ) =>
956- Effect . sync ( ( ) => {
957- aborted = true
958- } ) ,
959- ) ,
960- Effect . exit ,
961- )
952+ const abort = Effect . callback < void > ( ( resume ) => {
953+ if ( signal . aborted ) return resume ( Effect . void )
954+ const done = ( ) => resume ( Effect . void )
955+ signal . addEventListener ( "abort" , done , { once : true } )
956+ return Effect . sync ( ( ) => signal . removeEventListener ( "abort" , done ) )
957+ } )
958+ const next = yield * Effect . raceAll ( [
959+ handle . exitCode . pipe ( Effect . map ( ( code ) => ( { kind : "exit" as const , code } ) ) ) ,
960+ abort . pipe ( Effect . map ( ( ) => ( { kind : "abort" as const , code : 1 } ) ) ) ,
961+ ] )
962+
963+ if ( next . kind === "abort" ) {
964+ aborted = true
965+ yield * handle . kill ( { forceKillAfter : "3 seconds" } ) . pipe ( Effect . orDie )
966+ }
967+
968+ return next . code
969+ } ) . pipe ( Effect . scoped , Effect . exit )
962970
963971 if ( Exit . isFailure ( exit ) ) {
964972 if ( Cause . hasInterruptsOnly ( exit . cause ) ) return { code : 1 , stderr }
@@ -974,8 +982,8 @@ NOTE: At any point in time through this workflow you should feel free to ask the
974982 const unsandboxed = cfg . allow_unsandboxed_retry ? yield * Effect . promise ( ( ) => commandFamilies ( command ) ) : [ ]
975983 if ( command !== input . command && cfg . allow_unsandboxed_retry && sandbox . active ) {
976984 asked = true
977- try {
978- yield * permission . ask ( {
985+ const exit = yield * permission
986+ . ask ( {
979987 permission : "bash:unsandboxed" ,
980988 patterns : unsandboxed ,
981989 always : unsandboxed ,
@@ -991,28 +999,34 @@ NOTE: At any point in time through this workflow you should feel free to ask the
991999 } ,
9921000 ruleset : Permission . merge ( agent . permission , session . permission ?? [ ] ) ,
9931001 } )
1002+ . pipe ( Effect . exit )
1003+ if ( Exit . isSuccess ( exit ) ) {
9941004 proactive = true
995- } catch ( error ) {
1005+ } else {
9961006 rejected = true
997- log . info ( "proactive unsandboxed request rejected" , { error, sessionID : input . sessionID } )
1007+ log . info ( "proactive unsandboxed request rejected" , {
1008+ error : Cause . squash ( exit . cause ) ,
1009+ sessionID : input . sessionID ,
1010+ } )
9981011 }
9991012 }
10001013
10011014 let retried = false
10021015 let reason : SandboxSpawn . RetryReason | undefined
1003- let result
1004- try {
1005- result = yield * run ( proactive ? raw : call )
1006- } catch ( error ) {
1016+ let result : { code : number ; stderr : string }
1017+ const first = yield * run ( proactive ? raw : call ) . pipe ( Effect . exit )
1018+ if ( Exit . isFailure ( first ) ) {
1019+ const error = Cause . squash ( first . cause )
10071020 if ( rejected && ! proactive && sandbox . active ) {
10081021 const message = error instanceof Error ? error . message : String ( error )
10091022 throw new Error (
10101023 `Explicit unsandboxed request was rejected; sandboxed fallback failed before command start: ${ message } ` ,
10111024 error instanceof Error ? { cause : error } : undefined ,
10121025 )
10131026 }
1014- throw error
1027+ return yield * Effect . failCause ( first . cause )
10151028 }
1029+ result = first . value
10161030
10171031 if ( ! proactive ) {
10181032 reason = SandboxSpawn . retryReason ( {
@@ -1026,8 +1040,8 @@ NOTE: At any point in time through this workflow you should feel free to ask the
10261040
10271041 if ( cfg . allow_unsandboxed_retry && ! asked && ! aborted && reason ) {
10281042 asked = true
1029- try {
1030- yield * permission . ask ( {
1043+ const exit = yield * permission
1044+ . ask ( {
10311045 permission : "bash:unsandboxed" ,
10321046 patterns : unsandboxed ,
10331047 always : unsandboxed ,
@@ -1042,15 +1056,20 @@ NOTE: At any point in time through this workflow you should feel free to ask the
10421056 } ,
10431057 ruleset : Permission . merge ( agent . permission , session . permission ?? [ ] ) ,
10441058 } )
1059+ . pipe ( Effect . exit )
1060+ if ( Exit . isSuccess ( exit ) ) {
10451061 retried = true
10461062 output = ""
10471063 if ( part . state . status === "running" ) {
10481064 part . state . metadata = { output : "" , description : "" }
10491065 yield * sessions . updatePart ( part )
10501066 }
10511067 result = yield * run ( raw )
1052- } catch ( error ) {
1053- log . info ( "unsandboxed retry rejected" , { error, sessionID : input . sessionID } )
1068+ } else {
1069+ log . info ( "unsandboxed retry rejected" , {
1070+ error : Cause . squash ( exit . cause ) ,
1071+ sessionID : input . sessionID ,
1072+ } )
10541073 }
10551074 }
10561075
0 commit comments