feat: add hover action support (#3994)

Co-authored-by: LawyZheng <lawyzheng1106@gmail.com>
This commit is contained in:
Mohamed Khalil
2025-12-09 17:27:26 +02:00
committed by GitHub
parent 0e8d667959
commit f49b07f30d
22 changed files with 281 additions and 13 deletions

View File

@@ -91,6 +91,7 @@ def sanitize_variable_name(name: str) -> str:
ACTION_MAP = {
"click": "click",
"hover": "hover",
"input_text": "fill",
"upload_file": "upload_file",
"select_option": "select_option",
@@ -108,6 +109,7 @@ ACTION_MAP = {
}
ACTIONS_WITH_XPATH = [
"click",
"hover",
"input_text",
"type",
"fill",
@@ -276,6 +278,19 @@ def _action_to_stmt(act: dict[str, Any], task: dict[str, Any], assign_to_output:
),
)
)
elif method == "hover":
hold_seconds = act.get("hold_seconds")
if hold_seconds and hold_seconds > 0:
args.append(
cst.Arg(
keyword=cst.Name("hold_seconds"),
value=_value(hold_seconds),
whitespace_after_arg=cst.ParenthesizedWhitespace(
indent=True,
last_line=cst.SimpleWhitespace(INDENT),
),
)
)
elif method in ["type", "fill"]:
# Use context.parameters if field_name is available, otherwise fallback to direct value
if act.get("field_name"):

View File

@@ -136,6 +136,7 @@ class ScriptSkyvernPage(SkyvernPage):
ActionType.INPUT_TEXT: "⌨️",
ActionType.UPLOAD_FILE: "📤",
ActionType.DOWNLOAD_FILE: "📥",
ActionType.HOVER: "🖱️",
ActionType.SELECT_OPTION: "🎯",
ActionType.WAIT: "",
ActionType.SOLVE_CAPTCHA: "🔓",

View File

@@ -207,6 +207,27 @@ class SkyvernPage(Page):
return selector
@action_wrap(ActionType.HOVER)
async def hover(
self,
selector: str,
*,
timeout: float = settings.BROWSER_ACTION_TIMEOUT_MS,
hold_seconds: float = 0.0,
intention: str | None = None,
**kwargs: Any,
) -> str:
"""Move the mouse over the element identified by `selector`."""
if not selector:
raise ValueError("Hover requires a selector.")
locator = self.page.locator(selector, **kwargs)
await locator.scroll_into_view_if_needed()
await locator.hover(timeout=timeout)
if hold_seconds and hold_seconds > 0:
await asyncio.sleep(hold_seconds)
return selector
@overload
async def fill(
self,