import asyncio import json import logging import os import uuid from typing import Any, AsyncGenerator, Dict, Optional import gradio as gr # from browser_use.agent.service import Agent from browser_use.agent.views import ( AgentHistoryList, AgentOutput, ) from browser_use.browser.browser import BrowserConfig from browser_use.browser.context import BrowserContext, BrowserContextConfig from browser_use.browser.views import BrowserState from gradio.components import Component from langchain_core.language_models.chat_models import BaseChatModel from src.agent.browser_use.browser_use_agent import BrowserUseAgent from src.browser.custom_browser import CustomBrowser from src.controller.custom_controller import CustomController from src.utils import llm_provider from src.webui.webui_manager import WebuiManager logger = logging.getLogger(__name__) # --- Helper Functions --- (Defined at module level) async def _initialize_llm( provider: Optional[str], model_name: Optional[str], temperature: float, base_url: Optional[str], api_key: Optional[str], num_ctx: Optional[int] = None, ) -> Optional[BaseChatModel]: """Initializes the LLM based on settings. Returns None if provider/model is missing.""" if not provider or not model_name: logger.info("LLM Provider or Model Name not specified, LLM will be None.") return None try: # Use your actual LLM provider logic here logger.info( f"Initializing LLM: Provider={provider}, Model={model_name}, Temp={temperature}" ) # Example using a placeholder function llm = llm_provider.get_llm_model( provider=provider, model_name=model_name, temperature=temperature, base_url=base_url or None, api_key=api_key or None, # Add other relevant params like num_ctx for ollama num_ctx=num_ctx if provider == "ollama" else None, ) return llm except Exception as e: logger.error(f"Failed to initialize LLM: {e}", exc_info=True) gr.Warning( f"Failed to initialize LLM \'{model_name}\' for provider \'{provider}\\\'. Please check settings. Error: {e}" ) return None def _get_config_value( webui_manager: WebuiManager, comp_dict: Dict[gr.components.Component, Any], comp_id_suffix: str, default: Any = None, ) -> Any: """Safely get value from component dictionary using its ID suffix relative to the tab.""" # Assumes component ID format is "tab_name.comp_name" tab_name = "browser_use_agent" # Hardcode or derive if needed comp_id = f"{tab_name}.{comp_id_suffix}" # Need to find the component object first using the ID from the manager try: comp = webui_manager.get_component_by_id(comp_id) return comp_dict.get(comp, default) except KeyError: # Try accessing settings tabs as well for prefix in ["agent_settings", "browser_settings"]: try: comp_id = f"{prefix}.{comp_id_suffix}" comp = webui_manager.get_component_by_id(comp_id) return comp_dict.get(comp, default) except KeyError: continue logger.warning( f"Component with suffix \'{comp_id_suffix}\' not found in manager for value lookup." ) return default def _format_agent_output(model_output: AgentOutput) -> str: """Formats AgentOutput for display in the chatbot using JSON.""" content = "" if model_output: try: # Directly use model_dump if actions and current_state are Pydantic models action_dump = [ action.model_dump(exclude_none=True) for action in model_output.action ] state_dump = model_output.current_state.model_dump(exclude_none=True) model_output_dump = { "current_state": state_dump, "action": action_dump, } # Dump to JSON string with indentation json_string = json.dumps(model_output_dump, indent=4, ensure_ascii=False) # Wrap in
 for proper display in HTML
            content = f"
{json_string}
" except AttributeError as ae: logger.error( f"AttributeError during model dump: {ae}. Check if \'action\' or \'current_state\' or their items support \'model_dump\'." ) content = f"
Error: Could not format agent output (AttributeError: {ae}).\nRaw output: {str(model_output)}
" except Exception as e: logger.error(f"Error formatting agent output: {e}", exc_info=True) # Fallback to simple string representation on error content = f"
Error formatting agent output.\nRaw output:\n{str(model_output)}
" return content.strip() # --- Updated Callback Implementation --- async def _handle_new_step( webui_manager: WebuiManager, state: BrowserState, output: AgentOutput, step_num: int ): """Callback for each step taken by the agent, including screenshot display.""" # Use the correct chat history attribute name from the user\'s code if not hasattr(webui_manager, "bu_chat_history"): logger.error( "Attribute \'bu_chat_history\' not found in webui_manager! Cannot add chat message." ) # Initialize it maybe? Or raise an error? For now, log and potentially skip chat update. webui_manager.bu_chat_history = [] # Initialize if missing (consider if this is the right place) # return # Or stop if this is critical step_num -= 1 logger.info(f"Step {step_num} completed.") # --- Screenshot Handling --- screenshot_html = "" # Ensure state.screenshot exists and is not empty before proceeding # Use getattr for safer access screenshot_data = getattr(state, "screenshot", None) if screenshot_data: try: # Basic validation: check if it looks like base64 if ( isinstance(screenshot_data, str) and len(screenshot_data) > 100 ): # Arbitrary length check # *** UPDATED STYLE: Removed centering, adjusted width *** img_tag = f"""\"Step""" screenshot_html = ( img_tag + "
" ) # Use
for line break after inline-block image else: logger.warning( f"Screenshot for step {step_num} seems invalid (type: {type(screenshot_data)}, len: {len(screenshot_data) if isinstance(screenshot_data, str) else 'N/A'})." ) screenshot_html = "**[Invalid screenshot data]**
" except Exception as e: logger.error( f"Error processing or formatting screenshot for step {step_num}: {e}", exc_info=True, ) screenshot_html = "**[Error displaying screenshot]**
" else: logger.debug(f"No screenshot available for step {step_num}.") # --- Format Agent Output --- formatted_output = _format_agent_output(output) # Use the updated function # --- Combine and Append to Chat --- step_header = f"--- **Step {step_num}** ---" # Combine header, image (with line break), and JSON block final_content = step_header + "
" + screenshot_html + formatted_output chat_message = { "role": "assistant", "content": final_content.strip(), # Remove leading/trailing whitespace } # Append to the correct chat history list webui_manager.bu_chat_history.append(chat_message) await asyncio.sleep(0.05) def _handle_done(webui_manager: WebuiManager, history: AgentHistoryList): """Callback when the agent finishes the task (success or failure).""" logger.info( f"Agent task finished. Duration: {history.total_duration_seconds():.2f}s, Tokens: {history.total_input_tokens()}" ) final_summary = "**Task Completed**\n" final_summary += f"- Duration: {history.total_duration_seconds():.2f} seconds\n" final_summary += f"- Total Input Tokens: {history.total_input_tokens()}\n" # Or total tokens if available final_result = history.final_result() if final_result: final_summary += f"- Final Result: {final_result}\n" errors = history.errors() if errors and any(errors): final_summary += f"- **Errors:**\n```\n{errors}\n```\n" else: final_summary += "- Status: Success\n" webui_manager.bu_chat_history.append( {"role": "assistant", "content": final_summary} ) async def _ask_assistant_callback( webui_manager: WebuiManager, query: str, browser_context: BrowserContext ) -> Dict[str, Any]: """Callback triggered by the agent\'s ask_for_assistant action.""" logger.info("Agent requires assistance. Waiting for user input.") if not hasattr(webui_manager, "_chat_history"): logger.error("Chat history not found in webui_manager during ask_assistant!") return {"response": "Internal Error: Cannot display help request."} # type: ignore webui_manager.bu_chat_history.append( { "role": "assistant", "content": f"**Need Help:** {query}\nPlease provide information or perform the required action in the browser, then type your response/confirmation below and click \'Submit Response\'.", } ) # Use state stored in webui_manager webui_manager.bu_response_event = asyncio.Event() webui_manager.bu_user_help_response = None # Reset previous response try: logger.info("Waiting for user response event...") await asyncio.wait_for( webui_manager.bu_response_event.wait(), timeout=3600.0 ) # Long timeout logger.info("User response event received.") except asyncio.TimeoutError: logger.warning("Timeout waiting for user assistance.") webui_manager.bu_chat_history.append( { "role": "assistant", "content": "**Timeout:** No response received. Trying to proceed.", } ) webui_manager.bu_response_event = None # Clear the event return {"response": "Timeout: User did not respond."} # Inform the agent response = webui_manager.bu_user_help_response webui_manager.bu_chat_history.append( {"role": "user", "content": response} ) # Show user response in chat webui_manager.bu_response_event = ( None # Clear the event for the next potential request ) return {"response": response} # --- Core Agent Execution Logic --- (Needs access to webui_manager) async def run_agent_task( webui_manager_instance: WebuiManager, components: Dict[gr.components.Component, Any] ) -> AsyncGenerator[Dict[gr.components.Component, Any], None]: """Handles the entire lifecycle of initializing and running the agent.""" # --- Get Components --- # Need handles to specific UI components to update them user_input_comp = webui_manager_instance.get_component_by_id("browser_use_agent.user_input") run_button_comp = webui_manager_instance.get_component_by_id("browser_use_agent.run_button") stop_button_comp = webui_manager_instance.get_component_by_id( "browser_use_agent.stop_button" ) pause_resume_button_comp = webui_manager_instance.get_component_by_id( "browser_use_agent.pause_resume_button" ) clear_button_comp = webui_manager_instance.get_component_by_id( "browser_use_agent.clear_button" ) chatbot_comp = webui_manager_instance.get_component_by_id("browser_use_agent.chatbot") history_file_comp = webui_manager_instance.get_component_by_id( "browser_use_agent.agent_history_file" ) gif_comp = webui_manager_instance.get_component_by_id("browser_use_agent.recording_gif") browser_view_comp = webui_manager_instance.get_component_by_id( "browser_use_agent.browser_view" # --- Get Components ---and Initial UI Update --- task = components.get(user_input_comp, "").strip() if not task: gr.Warning("Please enter a task.") yield {run_button_comp: gr.update(interactive=True)} return # Set running state indirectly via _current_task if webui_manager_instance.bu_chat_history is None: webui_manager_instance.init_browser_use_agent() webui_manager_instance.bu_chat_history.append({"role": "user", "content": task}) yield { user_input_comp: gr.Textbox( value="", interactive=False, placeholder="Agent is running..." ), run_button_comp: gr.Button(value="⏳ Running...", interactive=False), stop_button_comp: gr.Button(interactive=True), pause_resume_button_comp: gr.Button(value="⏸️ Pause", interactive=True), clear_button_comp: gr.Button(interactive=False), chatbot_comp: gr.update(value=webui_manager_instance.bu_chat_history), history_file_comp: gr.update(value=None), gif_comp: gr.update(value=None), } # --- Agent Settings --- # Access settings values via components dict, getting IDs from webui_manager_instance def get_setting(key, default=None): comp = webui_manager_instance.id_to_component.get(f"agent_settings.{key}") return components.get(comp, default) if comp else default override_system_prompt = get_setting("override_system_prompt") or None extend_system_prompt = get_setting("extend_system_prompt") or None llm_provider_name = get_setting( "llm_provider", None ) # Default to None if not found llm_model_name = get_setting("llm_model_name", None) llm_temperature = get_setting("llm_temperature", 0.6) use_vision = get_setting("use_vision", True) ollama_num_ctx = get_setting("ollama_num_ctx", 16000) llm_base_url = get_setting("llm_base_url") or None llm_api_key = get_setting("llm_api_key") or None max_steps = get_setting("max_steps", 100) max_actions = get_setting("max_actions", 10) max_input_tokens = get_setting("max_input_tokens", 128000) tool_calling_str = get_setting("tool_calling_method", "auto") tool_calling_method = tool_calling_str if tool_calling_str != "None" else None mcp_server_config_comp = webui_manager_instance.id_to_component.get( "agent_settings.mcp_server_config" ) mcp_server_config_str = ( components.get(mcp_server_config_comp) if mcp_server_config_comp else None ) mcp_server_config = ( json.loads(mcp_server_config_str) if mcp_server_config_str else None ) # Planner LLM Settings (Optional) planner_llm_provider_name = get_setting("planner_llm_provider") or None planner_llm = None planner_use_vision = False if planner_llm_provider_name: planner_llm_model_name = get_setting("planner_llm_model_name") planner_llm_temperature = get_setting("planner_llm_temperature", 0.6) planner_ollama_num_ctx = get_setting("planner_ollama_num_ctx", 16000) planner_llm_base_url = get_setting("planner_llm_base_url") or None planner_llm_api_key = get_setting("planner_llm_api_key") or None planner_use_vision = get_setting("planner_use_vision", False) planner_llm = await _initialize_llm( planner_llm_provider_name, planner_llm_model_name, planner_llm_temperature, planner_llm_base_url, planner_llm_api_key, planner_ollama_num_ctx if planner_llm_provider_name == "ollama" else None, ) # --- Browser Settings --- def get_browser_setting(key, default=None): # This function is called within run_agent_task, which receives \'components\' as an argument. # \'components\' is a dictionary mapping Gradio components to their current values. # The issue is that webui_manager_instance.id_to_component only contains components that have been explicitly registered. # The browser settings components are registered in create_browser_settings_tab, but they are not directly passed to run_agent_task. # Instead, run_agent_task receives a dictionary of all components from the Gradio UI. # So, we need to retrieve the component from webui_manager_instance.id_to_component and then get its value from the \'components\' dictionary. comp = webui_manager_instance.id_to_component.get(f"browser_settings.{key}") return components.get(comp, default) if comp else default browser_binary_path = get_browser_setting("browser_binary_path") browser_user_data_dir = get_browser_setting("browser_user_data_dir") use_own_browser = get_browser_setting("use_own_browser", False) browser_headless = get_browser_setting("browser_headless", True) browser_viewport_width = get_browser_setting("browser_viewport_width", 1280) browser_viewport_height = get_browser_setting("browser_viewport_height", 1100) cdp_url = get_browser_setting("cdp_url") wss_url = get_browser_setting("wss_url") save_recording_path = get_browser_setting("save_recording_path") save_trace_path = get_browser_setting("save_trace_path") save_agent_history_path = get_browser_setting("save_agent_history_path") save_download_path = get_browser_setting("save_download_path") # --- Initialize Browser and Controller --- # --- Final UI Update --- yield { user_input_comp: gr.Textbox(interactive=True), run_button_comp: gr.Button(interactive=True), stop_button_comp: gr.Button(interactive=False), pause_resume_button_comp: gr.Button(interactive=False), clear_button_comp: gr.Button(interactive=True), chatbot_comp: gr.update(value=webui_manager.bu_chat_history), history_file_comp: webui_manager.bu_agent.agent_history_file if webui_manager.bu_agent else None, gif_comp: webui_manager.bu_agent.recording_gif if webui_manager.bu_agent else None, } def create_browser_use_agent_tab(webui_manager: WebuiManager): """ Creates the main browser use agent tab. """ with gr.Column(): gr.Markdown( """ ### 🤖 Run Agent """, elem_classes=["tab-header-text"], ) with gr.Row(): user_input = gr.Textbox( label="Task", placeholder="Enter your task here...", lines=3, interactive=True, ) webui_manager.register_component("browser_use_agent.user_input", user_input) with gr.Row(): run_button = gr.Button("🚀 Run Agent", interactive=True) webui_manager.register_component("browser_use_agent.run_button", run_button) stop_button = gr.Button("🛑 Stop", interactive=False) webui_manager.register_component("browser_use_agent.stop_button", stop_button) pause_resume_button = gr.Button("⏸️ Pause", interactive=False) webui_manager.register_component("browser_use_agent.pause_resume_button", pause_resume_button) clear_button = gr.Button("🧹 Clear", interactive=True) webui_manager.register_component("browser_use_agent.clear_button", clear_button) chatbot = gr.Chatbot(label="Agent Output", height=500, show_copy_button=True) webui_manager.register_component("browser_use_agent.chatbot", chatbot) agent_history_file = gr.File(label="Agent History File", interactive=False) webui_manager.register_component("browser_use_agent.agent_history_file", agent_history_file) recording_gif = gr.Image(label="Browser Recording", interactive=False, visible=False) webui_manager.register_component("browser_use_agent.recording_gif", recording_gif) browser_view = gr.Image(label="Browser View", interactive=False, visible=False) webui_manager.register_component("browser_use_agent.browser_view", browser_view) # User response input for ask_assistant_callback with gr.Row(): user_response_input = gr.Textbox( label="User Response (for Agent Assistance)", placeholder="Type your response to the agent here...", lines=1, interactive=False, ) webui_manager.register_component("browser_use_agent.user_response_input", user_response_input) submit_response_button = gr.Button("Submit Response", interactive=False) webui_manager.register_component("browser_use_agent.submit_response_button", submit_response_button) # Event Handlers run_event = run_button.click( run_agent_task.override(fn=lambda task_input, *settings_components_vals: run_agent_task(webui_manager, {user_input: task_input, **dict(zip(all_settings_components, settings_components_vals))})), inputs=[user_input, *all_settings_components], outputs=[ user_input, run_button, stop_button, pause_resume_button, clear_button, chatbot, agent_history_file, recording_gif, ], api_name="run_agent_task", ).then( lambda: gr.update(interactive=True), outputs=[run_button], queue=False, ) stop_button.click( lambda: run_event.cancel(), inputs=None, outputs=[ user_input, run_button, stop_button, pause_resume_button, clear_button, ], # queue=False, ) def pause_resume_agent(): if webui_manager.bu_current_task and not webui_manager.bu_current_task.done(): if webui_manager.bu_agent.is_paused(): webui_manager.bu_agent.resume() return gr.Button(value="⏸️ Pause") else: webui_manager.bu_agent.pause() return gr.Button(value="▶️ Resume") return gr.Button(value="⏸️ Pause") # Default state pause_resume_button.click( pause_resume_agent, inputs=None, outputs=[pause_resume_button], # queue=False, ) def clear_ui(): webui_manager.bu_chat_history = [] webui_manager.init_browser_use_agent() # Reset agent state return { user_input: gr.Textbox(value="", interactive=True), chatbot: gr.update(value=[]), agent_history_file: gr.update(value=None), recording_gif: gr.update(value=None, visible=False), run_button: gr.Button(interactive=True), stop_button: gr.Button(interactive=False), pause_resume_button: gr.Button(interactive=False), clear_button: gr.Button(interactive=True), user_response_input: gr.Textbox(interactive=False, value=""), submit_response_button: gr.Button(interactive=False), } clear_button.click( clear_ui, inputs=None, outputs=[ user_input, chatbot, agent_history_file, recording_gif, run_button, stop_button, pause_resume_button, clear_button, user_response_input, submit_response_button, ], # queue=False, ) # User response submission submit_response_button.click( lambda response: ( webui_manager.bu_response_event.set(), setattr(webui_manager, "bu_user_help_response", response), gr.Textbox(interactive=False, value=""), gr.Button(interactive=False), ), inputs=[user_response_input], outputs=[user_response_input, submit_response_button], # queue=False, ) # Link browser settings to agent run # These are the lines causing the KeyError webui_manager.get_component_by_id("browser_settings.browser_headless").change( lambda: None, # No direct output needed, just trigger update inputs=[ webui_manager.get_component_by_id("browser_settings.browser_headless"), webui_manager.get_component_by_id("browser_settings.browser_viewport_width"), webui_manager.get_component_by_id("browser_settings.browser_viewport_height"), webui_manager.get_component_by_id("browser_settings.use_own_browser"), webui_manager.get_component_by_id("browser_settings.keep_browser_open"), webui_manager.get_component_by_id("browser_settings.disable_security"), webui_manager.get_component_by_id("browser_settings.cdp_url"), webui_manager.get_component_by_id("browser_settings.wss_url"), webui_manager.get_component_by_id("browser_settings.save_recording_path"), webui_manager.get_component_by_id("browser_settings.save_trace_path"), webui_manager.get_component_by_id("browser_settings.save_agent_history_path"), webui_manager.get_component_by_id("browser_settings.save_download_path"), ], outputs=[], # queue=False, ) webui_manager.get_component_by_id("browser_settings.browser_viewport_width").change( lambda: None, # No direct output needed, just trigger update inputs=[ webui_manager.get_component_by_id("browser_settings.browser_headless"), webui_manager.get_component_by_id("browser_settings.browser_viewport_width"), webui_manager.get_component_by_id("browser_settings.browser_viewport_height"), webui_manager.get_component_by_id("browser_settings.use_own_browser"), webui_manager.get_component_by_id("browser_settings.keep_browser_open"), webui_manager.get_component_by_id("browser_settings.disable_security"), webui_manager.get_component_by_id("browser_settings.cdp_url"), webui_manager.get_component_by_id("browser_settings.wss_url"), webui_manager.get_component_by_id("browser_settings.save_recording_path"), webui_manager.get_component_by_id("browser_settings.save_trace_path"), webui_manager.get_component_by_id("browser_settings.save_agent_history_path"), webui_manager.get_component_by_id("browser_settings.save_download_path"), ], outputs=[], # queue=False, ) webui_manager.get_component_by_id("browser_settings.browser_viewport_height").change( lambda: None, # No direct output needed, just trigger update inputs=[ webui_manager.get_component_by_id("browser_settings.browser_headless"), webui_manager.get_component_by_id("browser_settings.browser_viewport_width"), webui_manager.get_component_by_id("browser_settings.browser_viewport_height"), webui_manager.get_component_by_id("browser_settings.use_own_browser"), webui_manager.get_component_by_id("browser_settings.keep_browser_open"), webui_manager.get_component_by_id("browser_settings.disable_security"), webui_manager.get_component_by_id("browser_settings.cdp_url"), webui_manager.get_component_by_id("browser_settings.wss_url"), webui_manager.get_component_by_id("browser_settings.save_recording_path"), webui_manager.get_component_by_id("browser_settings.save_trace_path"), webui_manager.get_component_by_id("browser_settings.save_agent_history_path"), webui_manager.get_component_by_id("browser_settings.save_download_path"), ], outputs=[], # queue=False, ) webui_manager.get_component_by_id("browser_settings.use_own_browser").change( lambda: None, # No direct output needed, just trigger update inputs=[ webui_manager.get_component_by_id("browser_settings.browser_headless"), webui_manager.get_component_by_id("browser_settings.browser_viewport_width"), webui_manager.get_component_by_id("browser_settings.browser_viewport_height"), webui_manager.get_component_by_id("browser_settings.use_own_browser"), webui_manager.get_component_by_id("browser_settings.keep_browser_open"), webui_manager.get_component_by_id("browser_settings.disable_security"), webui_manager.get_component_by_id("browser_settings.cdp_url"), webui_manager.get_component_by_id("browser_settings.wss_url"), webui_manager.get_component_by_id("browser_settings.save_recording_path"), webui_manager.get_component_by_id("browser_settings.save_trace_path"), webui_manager.get_component_by_id("browser_settings.save_agent_history_path"), webui_manager.get_component_by_id("browser_settings.save_download_path"), ], outputs=[], # queue=False, ) webui_manager.get_component_by_id("browser_settings.keep_browser_open").change( lambda: None, # No direct output needed, just trigger update inputs=[ webui_manager.get_component_by_id("browser_settings.browser_headless"), webui_manager.get_component_by_id("browser_settings.browser_viewport_width"), webui_manager.get_component_by_id("browser_settings.browser_viewport_height"), webui_manager.get_component_by_id("browser_settings.use_own_browser"), webui_manager.get_component_by_id("browser_settings.keep_browser_open"), webui_manager.get_component_by_id("browser_settings.disable_security"), webui_manager.get_component_by_id("browser_settings.cdp_url"), webui_manager.get_component_by_id("browser_settings.wss_url"), webui_manager.get_component_by_id("browser_settings.save_recording_path"), webui_manager.get_component_by_id("browser_settings.save_trace_path"), webui_manager.get_component_by_id("browser_settings.save_agent_history_path"), webui_manager.get_component_by_id("browser_settings.save_download_path"), ], outputs=[], # queue=False, ) webui_manager.get_component_by_id("browser_settings.disable_security").change( lambda: None, # No direct output needed, just trigger update inputs=[ webui_manager.get_component_by_id("browser_settings.browser_headless"), webui_manager.get_component_by_id("browser_settings.browser_viewport_width"), webui_manager.get_component_by_id("browser_settings.browser_viewport_height"), webui_manager.get_component_by_id("browser_settings.use_own_browser"), webui_manager.get_component_by_id("browser_settings.keep_browser_open"), webui_manager.get_component_by_id("browser_settings.disable_security"), webui_manager.get_component_by_id("browser_settings.cdp_url"), webui_manager.get_component_by_id("browser_settings.wss_url"), webui_manager.get_component_by_id("browser_settings.save_recording_path"), webui_manager.get_component_by_id("browser_settings.save_trace_path"), webui_manager.get_component_by_id("browser_settings.save_agent_history_path"), webui_manager.get_component_by_id("browser_settings.save_download_path"), ], outputs=[], # queue=False, ) webui_manager.get_component_by_id("browser_settings.cdp_url").change( lambda: None, # No direct output needed, just trigger update inputs=[ webui_manager.get_component_by_id("browser_settings.browser_headless"), webui_manager.get_component_by_id("browser_settings.browser_viewport_width"), webui_manager.get_component_by_id("browser_settings.browser_viewport_height"), webui_manager.get_component_by_id("browser_settings.use_own_browser"), webui_manager.get_component_by_id("browser_settings.keep_browser_open"), webui_manager.get_component_by_id("browser_settings.disable_security"), webui_manager.get_component_by_id("browser_settings.cdp_url"), webui_manager.get_component_by_id("browser_settings.wss_url"), webui_manager.get_component_by_id("browser_settings.save_recording_path"), webui_manager.get_component_by_id("browser_settings.save_trace_path"), webui_manager.get_component_by_id("browser_settings.save_agent_history_path"), webui_manager.get_component_by_id("browser_settings.save_download_path"), ], outputs=[], # queue=False, ) webui_manager.get_component_by_id("browser_settings.wss_url").change( lambda: None, # No direct output needed, just trigger update inputs=[ webui_manager.get_component_by_id("browser_settings.browser_headless"), webui_manager.get_component_by_id("browser_settings.browser_viewport_width"), webui_manager.get_component_by_id("browser_settings.browser_viewport_height"), webui_manager.get_component_by_id("browser_settings.use_own_browser"), webui_manager.get_component_by_id("browser_settings.keep_browser_open"), webui_manager.get_component_by_id("browser_settings.disable_security"), webui_manager.get_component_by_id("browser_settings.cdp_url"), webui_manager.get_component_by_id("browser_settings.wss_url"), webui_manager.get_component_by_id("browser_settings.save_recording_path"), webui_manager.get_component_by_id("browser_settings.save_trace_path"), webui_manager.get_component_by_id("browser_settings.save_agent_history_path"), webui_manager.get_component_by_id("browser_settings.save_download_path"), ], outputs=[], # queue=False, ) webui_manager.get_component_by_id("browser_settings.save_recording_path").change( lambda: None, # No direct output needed, just trigger update inputs=[ webui_manager.get_component_by_id("browser_settings.browser_headless"), webui_manager.get_component_by_id("browser_settings.browser_viewport_width"), webui_manager.get_component_by_id("browser_settings.browser_viewport_height"), webui_manager.get_component_by_id("browser_settings.use_own_browser"), webui_manager.get_component_by_id("browser_settings.keep_browser_open"), webui_manager.get_component_by_id("browser_settings.disable_security"), webui_manager.get_component_by_id("browser_settings.cdp_url"), webui_manager.get_component_by_id("browser_settings.wss_url"), webui_manager.get_component_by_id("browser_settings.save_recording_path"), webui_manager.get_component_by_id("browser_settings.save_trace_path"), webui_manager.get_component_by_id("browser_settings.save_agent_history_path"), webui_manager.get_component_by_id("browser_settings.save_download_path"), ], outputs=[], # queue=False, ) webui_manager.get_component_by_id("browser_settings.save_trace_path").change( lambda: None, # No direct output needed, just trigger update inputs=[ webui_manager.get_component_by_id("browser_settings.browser_headless"), webui_manager.get_component_by_id("browser_settings.browser_viewport_width"), webui_manager.get_component_by_id("browser_settings.browser_viewport_height"), webui_manager.get_component_by_id("browser_settings.use_own_browser"), webui_manager.get_component_by_id("browser_settings.keep_browser_open"), webui_manager.get_component_by_id("browser_settings.disable_security"), webui_manager.get_component_by_id("browser_settings.cdp_url"), webui_manager.get_component_by_id("browser_settings.wss_url"), webui_manager.get_component_by_id("browser_settings.save_recording_path"), webui_manager.get_component_by_id("browser_settings.save_trace_path"), webui_manager.get_component_by_id("browser_settings.save_agent_history_path"), webui_manager.get_component_by_id("browser_settings.save_download_path"), ], outputs=[], # queue=False, ) webui_manager.get_component_by_id("browser_settings.save_agent_history_path").change( lambda: None, # No direct output needed, just trigger update inputs=[ webui_manager.get_component_by_id("browser_settings.browser_headless"), webui_manager.get_component_by_id("browser_settings.browser_viewport_width"), webui_manager.get_component_by_id("browser_settings.browser_viewport_height"), webui_manager.get_component_by_id("browser_settings.use_own_browser"), webui_manager.get_component_by_id("browser_settings.keep_browser_open"), webui_manager.get_component_by_id("browser_settings.disable_security"), webui_manager.get_component_by_id("browser_settings.cdp_url"), webui_manager.get_component_by_id("browser_settings.wss_url"), webui_manager.get_component_by_id("browser_settings.save_recording_path"), webui_manager.get_component_by_id("browser_settings.save_trace_path"), webui_manager.get_component_by_id("browser_settings.save_agent_history_path"), webui_manager.get_component_by_id("browser_settings.save_download_path"), ], outputs=[], # queue=False, ) webui_manager.get_component_by_id("browser_settings.save_download_path").change( lambda: None, # No direct output needed, just trigger update inputs=[ webui_manager.get_component_by_id("browser_settings.browser_headless"), webui_manager.get_component_by_id("browser_settings.browser_viewport_width"), webui_manager.get_component_by_id("browser_settings.browser_viewport_height"), webui_manager.get_component_by_id("browser_settings.use_own_browser"), webui_manager.get_component_by_id("browser_settings.keep_browser_open"), webui_manager.get_component_by_id("browser_settings.disable_security"), webui_manager.get_component_by_id("browser_settings.cdp_url"), webui_manager.get_component_by_id("browser_settings.wss_url"), webui_manager.get_component_by_id("browser_settings.save_recording_path"), webui_manager.get_component_by_id("browser_settings.save_trace_path"), webui_manager.get_component_by_id("browser_settings.save_agent_history_path"), webui_manager.get_component_by_id("browser_settings.save_download_path"), ], outputs=[], # queue=False, )