@@ -99,14 +99,22 @@ def __init__(
9999 self .ui_manager : Optional [UIManager ] = UIManager () if gui_input_mode else None
100100 self ._take_screenshots = should_take_screenshots () or take_screenshots
101101 self .stake_id = stake_id
102- self ._screenshots_dir = os .path .join (get_proof_path (self .stake_id ) or screenshots_dir , "screenshots" )
102+ self ._screenshots_dir = os .path .join (
103+ get_proof_path (self .stake_id ) or screenshots_dir , "screenshots"
104+ )
103105 self ._record_video = should_record_video () or record_video
104- self ._video_dir = os .path .join (get_proof_path (self .stake_id ) or video_dir , "videos" )
106+ self ._video_dir = os .path .join (
107+ get_proof_path (self .stake_id ) or video_dir , "videos"
108+ )
105109 self ._playwright : Optional [Playwright ] = None
106110 self ._browser_context : Optional [BrowserContext ] = None
107111 self .__async_initialize_done = False
108- self ._latest_screenshot_bytes : Optional [bytes ] = None # Stores the latest screenshot bytes
109- self ._latest_video_path : Optional [str ] = None # Stores the latest video file path
112+ self ._latest_screenshot_bytes : Optional [bytes ] = (
113+ None # Stores the latest screenshot bytes
114+ )
115+ self ._latest_video_path : Optional [str ] = (
116+ None # Stores the latest video file path
117+ )
110118 self .log_requests_responses = should_capture_network () or log_requests_responses
111119 self .request_response_log_file = os .path .join (
112120 get_proof_path (self .stake_id ) or request_response_log_file ,
@@ -115,7 +123,9 @@ def __init__(
115123 self .request_response_logs : List [Dict ] = []
116124
117125 # Extension caching directory
118- self ._extension_cache_dir = os .path .join ("." , ".cache" , "browser" , self .browser_type , "extension" )
126+ self ._extension_cache_dir = os .path .join (
127+ "." , ".cache" , "browser" , self .browser_type , "extension"
128+ )
119129 self ._extension_path : Optional [str ] = None
120130
121131 async def async_initialize (self ) -> None :
@@ -201,9 +211,13 @@ async def prepare_extension(self) -> None:
201211 if response .status_code == 200 :
202212 with open (extension_file_path , "wb" ) as f :
203213 f .write (response .content )
204- logger .info (f"Extension downloaded and saved to { extension_file_path } " )
214+ logger .info (
215+ f"Extension downloaded and saved to { extension_file_path } "
216+ )
205217 else :
206- logger .error (f"Failed to download extension from { extension_url } , status { response .status_code } " )
218+ logger .error (
219+ f"Failed to download extension from { extension_url } , status { response .status_code } "
220+ )
207221 return
208222
209223 if self .browser_type == "chromium" :
@@ -254,9 +268,13 @@ async def create_browser_context(self) -> None:
254268 # Prepare the extension
255269 await self .prepare_extension ()
256270 if self ._record_video :
257- await self ._launch_browser_with_video (browser_type , user_dir , disable_args )
271+ await self ._launch_browser_with_video (
272+ browser_type , user_dir , disable_args
273+ )
258274 else :
259- await self ._launch_persistent_browser (browser_type , user_dir , disable_args )
275+ await self ._launch_persistent_browser (
276+ browser_type , user_dir , disable_args
277+ )
260278
261279 async def _launch_persistent_browser (
262280 self ,
@@ -288,7 +306,9 @@ async def _launch_persistent_browser(
288306 "extensions.webextensions.userScripts.enabled" : True , # Allow web extensions without prompt
289307 }
290308
291- self ._browser_context = await browser_type .launch_persistent_context (user_dir , ** browser_context_kwargs )
309+ self ._browser_context = await browser_type .launch_persistent_context (
310+ user_dir , ** browser_context_kwargs
311+ )
292312 except (PlaywrightError , OSError ) as e :
293313 await self ._handle_launch_exception (e , user_dir , browser_type , disable_args )
294314
@@ -308,7 +328,9 @@ async def _launch_browser_with_video(
308328
309329 try :
310330 if self .browser_type == "chromium" and self ._extension_path is not None :
311- disable_args .append (f"--disable-extensions-except={ self ._extension_path } " )
331+ disable_args .append (
332+ f"--disable-extensions-except={ self ._extension_path } "
333+ )
312334 disable_args .append (f"--load-extension={ self ._extension_path } " )
313335 browser = await browser_type .launch (
314336 headless = self .isheadless ,
@@ -318,8 +340,8 @@ async def _launch_browser_with_video(
318340 "record_video_dir" : self ._video_dir ,
319341 # "record_video_size": {"width": 1920, "height": 1080},
320342 }
321- if self .browser_type == "firefox" and self ._extension_path is not None :
322- context_options ["extensions" ] = [self ._extension_path ]
343+ # if self.browser_type == "firefox" and self._extension_path is not None:
344+ # context_options["extensions"] = [self._extension_path]
323345 self ._browser_context = await browser .new_context (** context_options ) # type: ignore
324346 except Exception as e :
325347 logger .error ("Failed to launch browser with video recording: %s" , e )
@@ -395,7 +417,9 @@ def log_request(self, request) -> None:
395417 # Encode in Base64 if it's binary data
396418 decoded_post_data = base64 .b64encode (post_data ).decode ("utf-8" )
397419 except Exception :
398- decoded_post_data = None # Handle cases where post_data is missing or inaccessible
420+ decoded_post_data = (
421+ None # Handle cases where post_data is missing or inaccessible
422+ )
399423
400424 log_entry = {
401425 "type" : "request" ,
@@ -461,7 +485,9 @@ async def get_current_page(self) -> Page:
461485 try :
462486 browser_context = await self .get_browser_context ()
463487 # Filter out closed pages
464- pages : list [Page ] = [page for page in browser_context .pages if not page .is_closed ()]
488+ pages : list [Page ] = [
489+ page for page in browser_context .pages if not page .is_closed ()
490+ ]
465491 page : Optional [Page ] = pages [- 1 ] if pages else None
466492 logger .debug (f"Current page: { page .url if page else None } " )
467493 if page is not None :
@@ -471,7 +497,9 @@ async def get_current_page(self) -> Page:
471497 await self .setup_request_response_logging (page )
472498 return page
473499 except Exception as e :
474- logger .warning (f"Error getting current page: { e } . Creating a new browser context." )
500+ logger .warning (
501+ f"Error getting current page: { e } . Creating a new browser context."
502+ )
475503 self ._browser_context = None
476504 await self .ensure_browser_context ()
477505 browser_context = await self .get_browser_context ()
@@ -526,25 +554,35 @@ async def set_iframe_navigation_handlers() -> None:
526554 for frame in page .frames :
527555 # Check if the frame is not the main frame
528556 if frame != page .main_frame :
529- frame .on ("domcontentloaded" , handle_navigation_for_mutation_observer )
557+ frame .on (
558+ "domcontentloaded" , handle_navigation_for_mutation_observer
559+ )
530560
531561 # Set event listeners for current iframes
532562 await set_iframe_navigation_handlers ()
533563
534564 # Expose the function for DOM mutation change detection
535- await page .expose_function ("dom_mutation_change_detected" , dom_mutation_change_detected )
565+ await page .expose_function (
566+ "dom_mutation_change_detected" , dom_mutation_change_detected
567+ )
536568
537569 # Optionally, you can add a listener to capture new iframes as they are added dynamically
538570 page .on (
539571 "frameattached" ,
540- lambda frame : frame .on ("domcontentloaded" , handle_navigation_for_mutation_observer ),
572+ lambda frame : frame .on (
573+ "domcontentloaded" , handle_navigation_for_mutation_observer
574+ ),
541575 )
542576
543577 async def set_overlay_state_handler (self ) -> None :
544578 logger .debug ("Setting overlay state handler" )
545579 context = await self .get_browser_context ()
546- await context .expose_function ("overlay_state_changed" , self .overlay_state_handler )
547- await context .expose_function ("show_steps_state_changed" , self .show_steps_state_handler )
580+ await context .expose_function (
581+ "overlay_state_changed" , self .overlay_state_handler
582+ )
583+ await context .expose_function (
584+ "show_steps_state_changed" , self .show_steps_state_handler
585+ )
548586
549587 async def overlay_state_handler (self , is_collapsed : bool ) -> None :
550588 page = await self .get_current_page ()
@@ -562,7 +600,9 @@ async def set_user_response_handler(self) -> None:
562600 context = await self .get_browser_context ()
563601 await context .expose_function ("user_response" , self .receive_user_response )
564602
565- async def notify_user (self , message : str , message_type : MessageType = MessageType .STEP ) -> None :
603+ async def notify_user (
604+ self , message : str , message_type : MessageType = MessageType .STEP
605+ ) -> None :
566606 """
567607 Notify the user with a message.
568608
@@ -613,7 +653,9 @@ async def notify_user(self, message: str, message_type: MessageType = MessageTyp
613653 page = await self .get_current_page ()
614654 await page .evaluate (js_code )
615655 except Exception as e :
616- logger .error (f'Failed to notify user with message "{ message } ". This may resolve after the page loads: { e } ' )
656+ logger .error (
657+ f'Failed to notify user with message "{ message } ". This may resolve after the page loads: { e } '
658+ )
617659 msg = message_type
618660 if not isinstance (msg , str ):
619661 msg = message_type .value # type: ignore
@@ -678,7 +720,9 @@ async def highlight_in_shadow_dom(selector, add_highlight) -> None:
678720 """ ,
679721 selector ,
680722 )
681- logger .debug (f"Applied pulsating border to element with selector { selector } to indicate operation" )
723+ logger .debug (
724+ f"Applied pulsating border to element with selector { selector } to indicate operation"
725+ )
682726 else :
683727 # Remove highlight from both regular and shadow DOM elements
684728 await page .evaluate (
@@ -729,7 +773,9 @@ async def highlight_in_shadow_dom(selector, add_highlight) -> None:
729773 """ ,
730774 selector ,
731775 )
732- logger .debug (f"Removed pulsating border from element with selector { selector } after operation" )
776+ logger .debug (
777+ f"Removed pulsating border from element with selector { selector } after operation"
778+ )
733779
734780 # Call the helper function to apply or remove highlight
735781 await highlight_in_shadow_dom (selector , add_highlight )
@@ -804,18 +850,24 @@ async def take_screenshots(
804850 screenshot_name += ".png"
805851 screenshot_path = os .path .join (self .get_screenshots_dir (), screenshot_name )
806852 try :
807- await page .wait_for_load_state (state = load_state , timeout = take_snapshot_timeout )
853+ await page .wait_for_load_state (
854+ state = load_state , timeout = take_snapshot_timeout
855+ )
808856 screenshot_bytes = await page .screenshot (
809857 path = screenshot_path ,
810858 full_page = full_page ,
811859 timeout = take_snapshot_timeout ,
812860 caret = "initial" ,
813861 scale = "device" ,
814862 )
815- self ._latest_screenshot_bytes = screenshot_bytes # Store the latest screenshot bytes
863+ self ._latest_screenshot_bytes = (
864+ screenshot_bytes # Store the latest screenshot bytes
865+ )
816866 logger .debug (f"Screenshot saved to: { screenshot_path } " )
817867 except Exception as e :
818- logger .error (f'Failed to take screenshot and save to "{ screenshot_path } ". Error: { e } ' )
868+ logger .error (
869+ f'Failed to take screenshot and save to "{ screenshot_path } ". Error: { e } '
870+ )
819871
820872 async def get_latest_screenshot_stream (self ) -> Optional [BytesIO ]:
821873 """
@@ -855,10 +907,16 @@ async def close_browser_context(self) -> None:
855907 if page .video :
856908 video_path = await page .video .path ()
857909 # rename the video file to include the page URL
858- video_name = f"{ self .stake_id } .webm" or os .path .basename (video_path )
910+ video_name = f"{ self .stake_id } .webm" or os .path .basename (
911+ video_path
912+ )
859913 video_dir = os .path .dirname (video_path )
860- video_url = "video_of" or page .url .replace ("://" , "_" ).replace ("/" , "_" )
861- new_video_path = os .path .join (video_dir , f"{ video_url } _{ video_name } " )
914+ video_url = "video_of" or page .url .replace (
915+ "://" , "_"
916+ ).replace ("/" , "_" )
917+ new_video_path = os .path .join (
918+ video_dir , f"{ video_url } _{ video_name } "
919+ )
862920 os .rename (video_path , new_video_path )
863921 self ._latest_video_path = new_video_path
864922 logger .info (f"Video recorded at: { new_video_path } " )
@@ -877,7 +935,9 @@ def log_user_message(self, message: str) -> None:
877935 if self .ui_manager :
878936 self .ui_manager .new_user_message (message )
879937
880- def log_system_message (self , message : str , message_type : MessageType = MessageType .STEP ) -> None :
938+ def log_system_message (
939+ self , message : str , message_type : MessageType = MessageType .STEP
940+ ) -> None :
881941 """
882942 Log a system message.
883943
@@ -899,15 +959,19 @@ async def update_processing_state(self, processing_state: str) -> None:
899959 if self .ui_manager :
900960 await self .ui_manager .update_processing_state (processing_state , page )
901961
902- async def command_completed (self , command : str , elapsed_time : Optional [float ] = None ) -> None :
962+ async def command_completed (
963+ self , command : str , elapsed_time : Optional [float ] = None
964+ ) -> None :
903965 """
904966 Notify the overlay that the command has been completed.
905967
906968 Args:
907969 command (str): The command that has been completed.
908970 elapsed_time (Optional[float]): The time taken to execute the command.
909971 """
910- logger .debug (f'Command "{ command } " has been completed. Focusing on the overlay input if it is open.' )
972+ logger .debug (
973+ f'Command "{ command } " has been completed. Focusing on the overlay input if it is open.'
974+ )
911975 page = await self .get_current_page ()
912976 if self .ui_manager :
913977 await self .ui_manager .command_completed (page , command , elapsed_time )
0 commit comments