Make SkyvernPage extend Playwright (#3934)

This commit is contained in:
Stanislav Novosad
2025-11-10 09:02:37 -07:00
committed by GitHub
parent 2e3879bc37
commit 23ebd72d4a
4 changed files with 88 additions and 234 deletions

View File

@@ -1,4 +1,4 @@
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Any
from playwright.async_api import BrowserContext, Page
@@ -9,10 +9,10 @@ if TYPE_CHECKING:
from skyvern.library.skyvern_sdk import SkyvernSdk
class SkyvernBrowser:
class SkyvernBrowser(BrowserContext):
"""A browser context wrapper that creates Skyvern-enabled pages.
This class wraps a Playwright BrowserContext and provides methods to create
This class extends Playwright BrowserContext and provides methods to create
SkyvernBrowserPage instances that combine traditional browser automation with
AI-powered task execution capabilities. It manages browser session state and
enables persistent browser sessions across multiple pages.
@@ -44,6 +44,7 @@ class SkyvernBrowser:
browser_session_id: str | None = None,
browser_address: str | None = None,
):
super().__init__(browser_context)
self._sdk = sdk
self._browser_context = browser_context
self._browser_session_id = browser_session_id
@@ -51,6 +52,18 @@ class SkyvernBrowser:
self.workflow_run_id: None | str = None
def __getattribute__(self, name: str) -> Any:
browser_context = object.__getattribute__(self, "_browser_context")
if hasattr(browser_context, name):
for cls in type(self).__mro__:
if cls is BrowserContext:
break
if name in cls.__dict__:
return object.__getattribute__(self, name)
return getattr(browser_context, name)
return object.__getattribute__(self, name)
@property
def browser_session_id(self) -> str | None:
return self._browser_session_id

View File

@@ -1,5 +1,5 @@
import asyncio
from typing import TYPE_CHECKING, Any, Pattern
from typing import TYPE_CHECKING, Any
from playwright.async_api import Page
@@ -8,7 +8,6 @@ from skyvern.client.types.workflow_run_response import WorkflowRunResponse
from skyvern.core.script_generations.skyvern_page import SkyvernPage
from skyvern.library.constants import DEFAULT_AGENT_HEARTBEAT_INTERVAL, DEFAULT_AGENT_TIMEOUT
from skyvern.library.skyvern_browser_page_ai import SdkSkyvernPageAi
from skyvern.library.skyvern_locator import SkyvernLocator
if TYPE_CHECKING:
from skyvern.library.skyvern_browser import SkyvernBrowser
@@ -249,117 +248,3 @@ class SkyvernBrowserPage(SkyvernPage):
```
"""
return await self._ai.ai_act(prompt)
async def reload(self, **kwargs: Any) -> None:
"""Reload the current page.
Args:
**kwargs: Additional options like timeout, wait_until, etc.
"""
await self.page.reload(**kwargs)
async def screenshot(self, **kwargs: Any) -> bytes:
"""Take a screenshot of the page.
Args:
**kwargs: Additional options like path, full_page, clip, type, quality, etc.
Returns:
bytes: The screenshot as bytes (unless path is specified, then saves to file).
"""
return await self.page.screenshot(**kwargs)
def locator(self, selector: str, **kwargs: Any) -> SkyvernLocator:
"""Find an element using a CSS selector or other selector syntax.
Args:
selector: CSS selector or other selector syntax (xpath=, text=, etc.).
**kwargs: Additional options like has, has_text, has_not, etc.
Returns:
SkyvernLocator object that can be used to perform actions or assertions.
"""
return SkyvernLocator(self.page.locator(selector, **kwargs))
def get_by_label(self, text: str | Pattern[str], **kwargs: Any) -> SkyvernLocator:
"""Find an input element by its associated label text.
Args:
text: Label text to search for (supports substring and regex matching).
**kwargs: Additional options like exact.
Returns:
SkyvernLocator object for the labeled input element.
"""
return SkyvernLocator(self.page.get_by_label(text, **kwargs))
def get_by_text(self, text: str | Pattern[str], **kwargs: Any) -> SkyvernLocator:
"""Find an element containing the specified text.
Args:
text: Text content to search for (supports substring and regex matching).
**kwargs: Additional options like exact.
Returns:
SkyvernLocator object for the element containing the text.
"""
return SkyvernLocator(self.page.get_by_text(text, **kwargs))
def get_by_title(self, text: str | Pattern[str], **kwargs: Any) -> SkyvernLocator:
"""Find an element by its title attribute.
Args:
text: Title attribute value to search for (supports substring and regex matching).
**kwargs: Additional options like exact.
Returns:
SkyvernLocator object for the element with matching title.
"""
return SkyvernLocator(self.page.get_by_title(text, **kwargs))
def get_by_role(self, role: str, **kwargs: Any) -> SkyvernLocator:
"""Find an element by its ARIA role.
Args:
role: ARIA role (e.g., "button", "textbox", "link").
**kwargs: Additional options like name, checked, pressed, etc.
Returns:
SkyvernLocator object for the element with matching role.
"""
return SkyvernLocator(self.page.get_by_role(role, **kwargs))
def get_by_placeholder(self, text: str | Pattern[str], **kwargs: Any) -> SkyvernLocator:
"""Find an input element by its placeholder text.
Args:
text: Placeholder text to search for (supports substring and regex matching).
**kwargs: Additional options like exact.
Returns:
SkyvernLocator object for the input element with matching placeholder.
"""
return SkyvernLocator(self.page.get_by_placeholder(text, **kwargs))
def get_by_alt_text(self, text: str | Pattern[str], **kwargs: Any) -> SkyvernLocator:
"""Find an element by its alt text (typically images).
Args:
text: Alt text to search for (supports substring and regex matching).
**kwargs: Additional options like exact.
Returns:
SkyvernLocator object for the element with matching alt text.
"""
return SkyvernLocator(self.page.get_by_alt_text(text, **kwargs))
def get_by_test_id(self, test_id: str) -> SkyvernLocator:
"""Find an element by its test ID attribute.
Args:
test_id: Test ID value to search for.
Returns:
SkyvernLocator object for the element with matching test ID.
"""
return SkyvernLocator(self.page.get_by_test_id(test_id))