Spaces:
No application file
No application file
| """Browser automation using Playwright for Manus AI agent.""" | |
| from typing import Optional, Dict, Any | |
| import asyncio | |
| import json | |
| class BrowserAutomation: | |
| """ | |
| Browser automation tool using Playwright. | |
| Can work with E2B sandbox browser or standalone. | |
| """ | |
| def __init__(self, playwright=None): | |
| self.playwright = playwright | |
| self.browser = None | |
| self.context = None | |
| self.page = None | |
| self._initialized = False | |
| async def initialize(self): | |
| """Initialize Playwright and browser.""" | |
| if self._initialized: | |
| return | |
| try: | |
| from playwright.async_api import async_playwright | |
| self.playwright = await async_playwright().start() | |
| self.browser = await self.playwright.chromium.launch(headless=True) | |
| self.context = await self.browser.new_context( | |
| viewport={"width": 1920, "height": 1080} | |
| ) | |
| self.page = await self.context.new_page() | |
| self._initialized = True | |
| except ImportError: | |
| raise Exception("Playwright not installed. Run: pip install playwright && playwright install") | |
| except Exception as e: | |
| raise Exception(f"Failed to initialize browser: {e}") | |
| async def navigate(self, url: str) -> Dict[str, Any]: | |
| """Navigate to a URL.""" | |
| if not self._initialized: | |
| await self.initialize() | |
| try: | |
| response = await self.page.goto(url, wait_until="domcontentloaded", timeout=30000) | |
| title = await self.page.title() | |
| return { | |
| "success": True, | |
| "url": str(self.page.url), | |
| "title": title, | |
| "status_code": response.status if response else None | |
| } | |
| except Exception as e: | |
| return {"success": False, "error": str(e)} | |
| async def click(self, selector: str, timeout: int = 5000) -> Dict[str, Any]: | |
| """Click an element by CSS selector.""" | |
| if not self._initialized: | |
| await self.initialize() | |
| try: | |
| await self.page.click(selector, timeout=timeout) | |
| return {"success": True, "selector": selector} | |
| except Exception as e: | |
| return {"success": False, "error": str(e)} | |
| async def type(self, selector: str, text: str, delay: int = 50) -> Dict[str, Any]: | |
| """Type text into an input field.""" | |
| if not self._initialized: | |
| await self.initialize() | |
| try: | |
| await self.page.fill(selector, text) | |
| return {"success": True, "selector": selector, "text": text} | |
| except Exception as e: | |
| return {"success": False, "error": str(e)} | |
| async def get_content(self, selector: Optional[str] = None) -> Dict[str, Any]: | |
| """Get page content or element content.""" | |
| if not self._initialized: | |
| await self.initialize() | |
| try: | |
| if selector: | |
| content = await self.page.text_content(selector) | |
| else: | |
| content = await self.page.content() | |
| return {"success": True, "content": content} | |
| except Exception as e: | |
| return {"success": False, "error": str(e)} | |
| async def screenshot(self, path: Optional[str] = None, full_page: bool = False) -> Dict[str, Any]: | |
| """Take a screenshot.""" | |
| if not self._initialized: | |
| await self.initialize() | |
| try: | |
| if path: | |
| await self.page.screenshot(path=path, full_page=full_page) | |
| return {"success": True, "path": path} | |
| else: | |
| # Return base64 encoded screenshot | |
| encoded = await self.page.screenshot() | |
| return {"success": True, "screenshot": encoded} | |
| except Exception as e: | |
| return {"success": False, "error": str(e)} | |
| async def evaluate(self, script: str) -> Dict[str, Any]: | |
| """Execute JavaScript on the page.""" | |
| if not self._initialized: | |
| await self.initialize() | |
| try: | |
| result = await self.page.evaluate(script) | |
| return {"success": True, "result": result} | |
| except Exception as e: | |
| return {"success": False, "error": str(e)} | |
| async def wait_for_selector(self, selector: str, timeout: int = 5000) -> Dict[str, Any]: | |
| """Wait for an element to appear.""" | |
| if not self._initialized: | |
| await self.initialize() | |
| try: | |
| await self.page.wait_for_selector(selector, timeout=timeout) | |
| return {"success": True, "selector": selector} | |
| except Exception as e: | |
| return {"success": False, "error": str(e)} | |
| async def close(self): | |
| """Close the browser.""" | |
| if self.browser: | |
| await self.browser.close() | |
| if self.playwright: | |
| await self.playwright.stop() | |
| self._initialized = False | |
| # Standalone browser tool for use without E2B | |
| async def create_browser_tool() -> BrowserAutomation: | |
| """Create a standalone browser automation tool.""" | |
| return BrowserAutomation() | |
| # Integration with E2B sandbox | |
| class E2BBrowserTool: | |
| """Browser tool that runs in E2B sandbox with Playwright installed.""" | |
| def __init__(self, sandbox): | |
| self.sandbox = sandbox | |
| async def execute(self, action: str, **params) -> Dict[str, Any]: | |
| """Execute browser action in E2B sandbox.""" | |
| try: | |
| if action == "install": | |
| # Install Playwright in sandbox | |
| result = await self.sandbox.commands.run( | |
| "pip install playwright && playwright install chromium --with-deps", | |
| timeout=300 | |
| ) | |
| return {"success": True, "output": result.stdout} | |
| elif action == "navigate": | |
| # For E2B, we'd need to run a script | |
| script = f""" | |
| import asyncio | |
| from playwright.async_api import async_playwright | |
| async def main(): | |
| async with async_playwright() as p: | |
| browser = await p.chromium.launch(headless=True) | |
| page = await browser.new_page() | |
| await page.goto("{params.get('url', '')}") | |
| title = await page.title() | |
| await browser.close() | |
| return title | |
| result = asyncio.run(main()) | |
| print(result) | |
| """ | |
| result = await self.sandbox.commands.run( | |
| f"python3 -c '{script.replace(chr(39), chr(39)*3)}'", | |
| timeout=60 | |
| ) | |
| return {"success": True, "output": result.stdout, "url": params.get("url")} | |
| else: | |
| return {"success": False, "error": f"Unknown action: {action}"} | |
| except Exception as e: | |
| return {"success": False, "error": str(e)} |