@@ -29,7 +29,7 @@ def execute_browser_command(command: Dict[str, Any]) -> Dict[str, Any]:
2929
3030 Args:
3131 command: Dictionary containing:
32- - command_type: 'start_session', 'act', 'script', 'end_session', or 'validate_profile '
32+ - command_type: 'start_session', 'act', 'script', 'end_session', 'validate_profile', or 'setup_login '
3333 - prompt: Natural language instruction (for 'act')
3434 - steps: List of script steps (for 'script')
3535 - starting_page: Initial URL (for 'start_session' or 'script')
@@ -41,6 +41,7 @@ def execute_browser_command(command: Dict[str, Any]) -> Dict[str, Any]:
4141 - schema: JSON schema for output
4242 - headless: Run headless mode
4343 - record_video: Record video
44+ - profile_name: Profile name (for 'setup_login')
4445
4546 Returns:
4647 Dictionary with execution result
@@ -58,6 +59,8 @@ def execute_browser_command(command: Dict[str, Any]) -> Dict[str, Any]:
5859 return end_session (command )
5960 elif command_type == 'validate_profile' :
6061 return validate_profile (command )
62+ elif command_type == 'setup_login' :
63+ return setup_login (command )
6164 else :
6265 return {
6366 "success" : False ,
@@ -160,14 +163,16 @@ def execute_act(command: Dict[str, Any]) -> Dict[str, Any]:
160163 print ("[DEMO MODE] Forcing profile to: Bt_broadband" , file = sys .stderr )
161164 from profile_manager import ProfileManager
162165 profile_manager = ProfileManager ()
166+ profile_name = "Bt_broadband"
163167 try :
164- profile_config = profile_manager .get_nova_act_config ("Bt_broadband" , clone_for_parallel = False )
168+ profile_config = profile_manager .get_nova_act_config (profile_name , clone_for_parallel = False )
165169 user_data_dir = profile_config ["user_data_dir" ]
166170 clone_user_data_dir = profile_config ["clone_user_data_dir" ]
167- print (f"[DEMO MODE] Using profile path: { user_data_dir } " , file = sys .stderr )
171+ print (f"[DEMO MODE] Loaded profile ' { profile_name } ' from path: { user_data_dir } " , file = sys .stderr )
168172 except Exception as e :
169- print (f"[DEMO MODE] Warning: Could not load Bt_broadband profile: { e } " , file = sys .stderr )
173+ print (f"[DEMO MODE] Warning: Could not load { profile_name } profile: { e } " , file = sys .stderr )
170174 print (f"[DEMO MODE] Continuing with original user_data_dir: { user_data_dir } " , file = sys .stderr )
175+ profile_name = "default" if not user_data_dir else "custom"
171176
172177 # Create boto3 session with local credentials
173178 boto_session = boto3 .Session (profile_name = aws_profile )
@@ -213,6 +218,18 @@ def execute_act(command: Dict[str, Any]) -> Dict[str, Any]:
213218 else :
214219 nova_act_kwargs ["boto_session" ] = boto_session
215220
221+ # Log comprehensive session startup information
222+ print (f"[INFO] Starting browser session with:" , file = sys .stderr )
223+ print (f" - Profile: { profile_name } " , file = sys .stderr )
224+ print (f" - Profile Path: { user_data_dir } " , file = sys .stderr )
225+ print (f" - Headless Mode: { headless } " , file = sys .stderr )
226+ print (f" - Clone Profile: { clone_user_data_dir if clone_user_data_dir is not None else 'not set (NovaAct default)' } " , file = sys .stderr )
227+ print (f" - Starting Page: { starting_page or 'none' } " , file = sys .stderr )
228+ print (f" - Record Video: { record_video } " , file = sys .stderr )
229+ print (f" - Max Steps: { max_steps } " , file = sys .stderr )
230+ print (f" - Timeout: { timeout } s" , file = sys .stderr )
231+ print (f" - Session ID: { session_id or 'auto-generated' } " , file = sys .stderr )
232+
216233 with NovaAct (** nova_act_kwargs ) as nova :
217234 # Execute act command
218235 result = nova .act (
@@ -503,6 +520,131 @@ def validate_profile(command: Dict[str, Any]) -> Dict[str, Any]:
503520 return out
504521
505522
523+ def setup_login (command : Dict [str , Any ]) -> Dict [str , Any ]:
524+ """Setup interactive login for a profile.
525+
526+ Opens a browser with the profile's user_data_dir, navigates to the starting_url,
527+ and waits for a timeout period to allow the user to manually log in.
528+ When the browser closes or timeout expires, the session is automatically saved.
529+
530+ Args:
531+ command: Dictionary containing:
532+ - profile_name: Name of the profile
533+ - starting_url: URL to navigate to for login
534+ - timeout: Timeout in seconds (default: 300 = 5 minutes)
535+
536+ Returns:
537+ Dictionary with success status
538+ """
539+ profile_name = command .get ("profile_name" )
540+ starting_url = command .get ("starting_url" )
541+
542+ if not profile_name :
543+ return {"success" : False , "error" : "profile_name is required" }
544+ if not starting_url :
545+ return {"success" : False , "error" : "starting_url is required" }
546+
547+ try :
548+ from profile_manager import ProfileManager
549+
550+ # Initialize profile manager
551+ profile_manager = ProfileManager ()
552+
553+ # Check if profile exists, create if not
554+ profile = profile_manager .get_profile (profile_name )
555+ if not profile :
556+ print (f"Creating new profile: { profile_name } " , file = sys .stderr )
557+ profile = profile_manager .create_profile (
558+ profile_name = profile_name ,
559+ description = f"Profile with authenticated session for { starting_url } " ,
560+ tags = ["authenticated" ],
561+ auto_login_sites = [starting_url ]
562+ )
563+ else :
564+ print (f"Using existing profile: { profile_name } " , file = sys .stderr )
565+
566+ # Mark profile as requiring human login
567+ profile_manager .mark_profile_for_login (
568+ profile_name = profile_name ,
569+ requires_human = True ,
570+ notes = f"Manual login required for { starting_url } "
571+ )
572+
573+ # Get Nova Act config
574+ config = profile_manager .get_nova_act_config (profile_name , clone_for_parallel = False )
575+ user_data_dir = config ["user_data_dir" ]
576+
577+ # Determine timeout (default 5 minutes)
578+ timeout = command .get ("timeout" , 300 )
579+
580+ # Get authentication credentials
581+ nova_act_api_key = os .environ .get ('NOVA_ACT_API_KEY' )
582+ boto_session = None
583+ if not nova_act_api_key :
584+ try :
585+ aws_profile = command .get ('aws_profile' , 'browser-agent' )
586+ boto_session = boto3 .Session (profile_name = aws_profile )
587+ except Exception :
588+ pass
589+
590+ # Build NovaAct kwargs
591+ nova_act_kwargs = {
592+ "starting_page" : starting_url ,
593+ "user_data_dir" : user_data_dir ,
594+ "clone_user_data_dir" : False , # Don't clone to preserve session
595+ "headless" : False , # Must be visible for human login
596+ "ignore_https_errors" : True ,
597+ }
598+
599+ if nova_act_api_key :
600+ nova_act_kwargs ["nova_act_api_key" ] = nova_act_api_key
601+ elif boto_session :
602+ nova_act_kwargs ["boto_session" ] = boto_session
603+
604+ print (f"" , file = sys .stderr )
605+ print (f"╔═══════════════════════════════════════════════════════════╗" , file = sys .stderr )
606+ print (f"║ PROFILE LOGIN SETUP ║" , file = sys .stderr )
607+ print (f"╠═══════════════════════════════════════════════════════════╣" , file = sys .stderr )
608+ print (f"║ Profile: { profile_name :<48} ║" , file = sys .stderr )
609+ print (f"║ URL: { starting_url [:48 ]:<48} ║" , file = sys .stderr )
610+ print (f"║ Timeout: { timeout } seconds{ '' :<38} ║" , file = sys .stderr )
611+ print (f"╠═══════════════════════════════════════════════════════════╣" , file = sys .stderr )
612+ print (f"║ A browser window will open. Please log in manually. ║" , file = sys .stderr )
613+ print (f"║ The browser will stay open for { timeout // 60 } minutes.{ '' :<23} ║" , file = sys .stderr )
614+ print (f"║ Your login session will be saved automatically. ║" , file = sys .stderr )
615+ print (f"║ You can close the browser when done. ║" , file = sys .stderr )
616+ print (f"╚═══════════════════════════════════════════════════════════╝" , file = sys .stderr )
617+ print (f"" , file = sys .stderr )
618+
619+ # Open browser for manual login
620+ import time
621+ with NovaAct (** nova_act_kwargs ) as nova :
622+ # Just wait for the timeout - user can log in during this time
623+ # The browser will stay open and visible
624+ print (f"Browser opened. Waiting { timeout } seconds for you to complete login..." , file = sys .stderr )
625+ time .sleep (timeout )
626+ print (f"Timeout reached. Closing browser and saving session..." , file = sys .stderr )
627+
628+ print (f"" , file = sys .stderr )
629+ print (f"✓ Profile '{ profile_name } ' login setup completed!" , file = sys .stderr )
630+ print (f" User data directory: { user_data_dir } " , file = sys .stderr )
631+ print (f" Future scripts can reuse this authenticated session" , file = sys .stderr )
632+
633+ return {
634+ "success" : True ,
635+ "message" : f"Login setup completed for profile '{ profile_name } '" ,
636+ "profile_name" : profile_name ,
637+ "user_data_dir" : user_data_dir ,
638+ }
639+
640+ except Exception as e :
641+ return {
642+ "success" : False ,
643+ "error" : f"Failed to setup login: { str (e )} " ,
644+ "traceback" : traceback .format_exc ()
645+ }
646+
647+
506648def main ():
507649 """
508650 Main entry point
0 commit comments