WebCrawler / src /webui /webui_manager.py
Carlos Gonzalez
Add application file
b1f90a5
import json
from collections.abc import Generator
from typing import TYPE_CHECKING
import os
import gradio as gr
from datetime import datetime
from typing import Optional, Dict, List, Any
import uuid
import asyncio
from gradio.components import Component
from browser_use.browser.browser import Browser
from browser_use.browser.context import BrowserContext
from browser_use.agent.service import Agent
from src.browser.custom_browser import CustomBrowser
from src.browser.custom_context import CustomBrowserContext
from src.controller.custom_controller import CustomController
from src.agent.deep_research.deep_research_agent import DeepResearchAgent
class WebuiManager:
def __init__(self, settings_save_dir: str = "./tmp/webui_settings"):
self.id_to_component: dict[str, Component] = {}
self.component_to_id: dict[Component, str] = {}
self.settings_save_dir = settings_save_dir
os.makedirs(self.settings_save_dir, exist_ok=True)
# Add type annotation for vayner_pdf_report
self.vayner_pdf_report: Optional[str] = None
def init_browser_use_agent(self) -> None:
"""
init browser use agent
"""
self.bu_agent: Optional[Agent] = None
self.bu_browser: Optional[CustomBrowser] = None
self.bu_browser_context: Optional[CustomBrowserContext] = None
self.bu_controller: Optional[CustomController] = None
self.bu_chat_history: List[Dict[str, Optional[str]]] = []
self.bu_response_event: Optional[asyncio.Event] = None
self.bu_user_help_response: Optional[str] = None
self.bu_current_task: Optional[asyncio.Task] = None
self.bu_agent_task_id: Optional[str] = None
self.bu_task_metrics: Optional[Dict[str, Any]] = None
def init_vayner_client_research(self) -> None:
"""
Initialize Vayner Client Research components and state
"""
if not hasattr(self, "vayner_chat_history"):
self.vayner_chat_history = []
if not hasattr(self, "vayner_pdf_report"):
self.vayner_pdf_report = None
if not hasattr(self, "vayner_controller"):
self.vayner_controller = None
if not hasattr(self, "vayner_browser"):
self.vayner_browser = None
if not hasattr(self, "vayner_browser_context"):
self.vayner_browser_context = None
if not hasattr(self, "vayner_agent"):
self.vayner_agent = None
if not hasattr(self, "vayner_current_task"):
self.vayner_current_task = None
# Initialize data collections for PDF report
if not hasattr(self, "vayner_screenshots"):
self.vayner_screenshots = []
if not hasattr(self, "vayner_business_info"):
self.vayner_business_info = []
if not hasattr(self, "vayner_keyword_data"):
self.vayner_keyword_data = []
if not hasattr(self, "vayner_ranking_data"):
self.vayner_ranking_data = []
if not hasattr(self, "vayner_current_business"):
self.vayner_current_business = "Unknown Business"
# New: keyword table rows for third page
if not hasattr(self, "vayner_keyword_table_rows"):
self.vayner_keyword_table_rows = []
# Queue for updates during task execution
if not hasattr(self, "update_queue"):
self.update_queue = []
def init_deep_research_agent(self) -> None:
"""
init deep research agent
"""
self.dr_agent: Optional[DeepResearchAgent] = None
self.dr_current_task = None
self.dr_agent_task_id: Optional[str] = None
self.dr_save_dir: Optional[str] = None
def add_components(self, tab_name: str, components_dict: dict[str, "Component"]) -> None:
"""
Add tab components
"""
for comp_name, component in components_dict.items():
comp_id = f"{tab_name}.{comp_name}"
self.id_to_component[comp_id] = component
self.component_to_id[component] = comp_id
def get_components(self) -> list["Component"]:
"""
Get all components
"""
return list(self.id_to_component.values())
def get_component_by_id(self, comp_id: str) -> Optional["Component"]:
"""
Get component by id. Returns None if not found.
"""
return self.id_to_component.get(comp_id, None)
def get_id_by_component(self, comp: "Component") -> str:
"""
Get id by component. Raises KeyError if not found.
"""
return self.component_to_id[comp]
def save_config(self, components: Dict["Component", str]) -> str:
"""
Save config
"""
cur_settings = {}
for comp in components:
if not isinstance(comp, gr.Button) and not isinstance(comp, gr.File) and str(
getattr(comp, "interactive", True)).lower() != "false":
comp_id = self.get_id_by_component(comp)
cur_settings[comp_id] = components[comp]
config_name = datetime.now().strftime("%Y%m%d-%H%M%S")
with open(os.path.join(self.settings_save_dir, f"{config_name}.json"), "w") as fw:
json.dump(cur_settings, fw, indent=4)
return os.path.join(self.settings_save_dir, f"{config_name}.json")
def load_config(self, config_path: str):
"""
Load config
"""
with open(config_path, "r") as fr:
ui_settings = json.load(fr)
update_components = {}
for comp_id, comp_val in ui_settings.items():
if comp_id in self.id_to_component:
comp = self.id_to_component[comp_id]
update_components[comp] = gr.update(value=comp_val)
config_status = self.id_to_component["load_save_config.config_status"]
update_components.update(
{
config_status: gr.update(value=f"Successfully loaded config: {config_path}")
}
)
yield update_components