From 3223a97dc61366f7cbda815242c9354bff25ae9d Mon Sep 17 00:00:00 2001 From: Alex Rothberg Date: Thu, 25 May 2023 17:10:39 -0400 Subject: [PATCH] Add visible_only and strict_mode options to ClickTool (#4088) Partially addresses: https://github.com/hwchase17/langchain/issues/4066 --- langchain/tools/playwright/click.py | 42 +++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/langchain/tools/playwright/click.py b/langchain/tools/playwright/click.py index eb68b23f..583bbb50 100644 --- a/langchain/tools/playwright/click.py +++ b/langchain/tools/playwright/click.py @@ -26,6 +26,18 @@ class ClickTool(BaseBrowserTool): description: str = "Click on an element with the given CSS selector" args_schema: Type[BaseModel] = ClickToolInput + visible_only: bool = True + """Whether to consider only visible elements.""" + playwright_strict: bool = False + """Whether to employ Playwright's strict mode when clicking on elements.""" + playwright_timeout: float = 1_000 + """Timeout (in ms) for Playwright to wait for element to be ready.""" + + def _selector_effective(self, selector: str) -> str: + if not self.visible_only: + return selector + return f"{selector} >> visible=1" + def _run( self, selector: str, @@ -36,11 +48,18 @@ class ClickTool(BaseBrowserTool): raise ValueError(f"Synchronous browser not provided to {self.name}") page = get_current_page(self.sync_browser) # Navigate to the desired webpage before using this tool + selector_effective = self._selector_effective(selector=selector) + from playwright.sync_api import TimeoutError as PlaywrightTimeoutError + try: - page.click(selector) - return f"Clicked element '{selector}'" - except Exception as e: - return f"Error '{e}'" + page.click( + selector_effective, + strict=self.playwright_strict, + timeout=self.playwright_timeout, + ) + except PlaywrightTimeoutError: + return f"Unable to click on element '{selector}'" + return f"Clicked element '{selector}'" async def _arun( self, @@ -52,8 +71,15 @@ class ClickTool(BaseBrowserTool): raise ValueError(f"Asynchronous browser not provided to {self.name}") page = await aget_current_page(self.async_browser) # Navigate to the desired webpage before using this tool + selector_effective = self._selector_effective(selector=selector) + from playwright.async_api import TimeoutError as PlaywrightTimeoutError + try: - await page.click(selector) - return f"Clicked element '{selector}'" - except Exception as e: - return f"Error '{e}'" + await page.click( + selector_effective, + strict=self.playwright_strict, + timeout=self.playwright_timeout, + ) + except PlaywrightTimeoutError: + return f"Unable to click on element '{selector}'" + return f"Clicked element '{selector}'"