import asyncio
import base64
import json
from typing import Generic, Optional, TypeVar
from browser_use import Browser as BrowserUseBrowser
from browser_use import BrowserConfig
from browser_use.browser.context import BrowserContext, BrowserContextConfig
from browser_use.dom.service import DomService
from pydantic import Field, field_validator
from pydantic_core.core_schema import ValidationInfo
from app.config import config
from app.llm import LLM
from app.tool.base import BaseTool, ToolResult
from app.tool.web_search import WebSearch
Context = TypeVar("Context")
class BrowserUseTool(BaseTool, Generic[Context]):
name: str = "browser_use"
description: str = "A powerful browser automation tool"
parameters: dict = {...} # Keeping full parameters intact
lock: asyncio.Lock = Field(default_factory=asyncio.Lock)
browser: Optional[BrowserUseBrowser] = Field(default=None, exclude=True)
context: Optional[BrowserContext] = Field(default=None, exclude=True)
dom_service: Optional[DomService] = Field(default=None, exclude=True)
web_search_tool: WebSearch = Field(default_factory=WebSearch, exclude=True)
llm: Optional[LLM] = Field(default_factory=LLM)
async def extract_content(self, goal: str, page_content: str) -> ToolResult:
"""Extract specific information from a webpage based on a goal."""
messages = [{"role": "system", "content": f"Extract relevant information
for: {goal}"}]
response = await self.llm.ask(messages) # Updated from ask_tool
extracted_content = json.loads(response.content) if response else {}
return ToolResult(output=f"Extracted from page:\n{extracted_content}\n")
async def execute(self, action: str, **kwargs) -> ToolResult:
"""Execute browser action."""
async with self.lock:
context = await self._ensure_browser_initialized()
if action == "extract_content":
return await self.extract_content(kwargs.get("goal", ""),
kwargs.get("page_content", ""))
# Other browser interactions remain unchanged...
async def cleanup(self):
"""Clean up browser resources."""
async with self.lock:
if self.context is not None:
await self.context.close()
self.context = None
self.dom_service = None
if self.browser is not None:
await self.browser.close()
self.browser = None