browse.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import os
  2. import base64
  3. from dataclasses import dataclass
  4. from opendevin.observation import BrowserOutputObservation
  5. from opendevin.schema import ActionType
  6. from typing import TYPE_CHECKING
  7. from playwright.async_api import async_playwright
  8. from .base import ExecutableAction
  9. if TYPE_CHECKING:
  10. from opendevin.controller import AgentController
  11. @dataclass
  12. class BrowseURLAction(ExecutableAction):
  13. url: str
  14. action: str = ActionType.BROWSE
  15. async def run(self, controller: 'AgentController') -> BrowserOutputObservation: # type: ignore
  16. asked_url = self.url
  17. if not asked_url.startswith('http'):
  18. asked_url = os.path.abspath(os.curdir) + self.url
  19. try:
  20. async with async_playwright() as p:
  21. browser = await p.chromium.launch()
  22. page = await browser.new_page()
  23. response = await page.goto(asked_url)
  24. try:
  25. # domcontentloaded: Wait for the DOMContentLoaded event to be fired.
  26. # load: Wait for the load event to be fired.
  27. # networkidle: Wait until there are no more network connections
  28. await page.wait_for_load_state('networkidle', timeout=3000)
  29. except TimeoutError:
  30. pass
  31. # content = await page.content()
  32. inner_text = await page.evaluate('() => document.body.innerText')
  33. screenshot_bytes = await page.screenshot(full_page=True)
  34. await browser.close()
  35. screenshot_base64 = base64.b64encode(screenshot_bytes).decode('utf-8')
  36. return BrowserOutputObservation(
  37. content=inner_text, # HTML content of the page
  38. screenshot=screenshot_base64, # Base64-encoded screenshot
  39. url=asked_url,
  40. status_code=response.status if response else 0, # HTTP status code
  41. )
  42. except Exception as e:
  43. return BrowserOutputObservation(
  44. content=str(e), screenshot='', error=True, url=asked_url
  45. )
  46. @property
  47. def message(self) -> str:
  48. return f'Browsing URL: {self.url}'