from __future__ import annotations from typing import Any from leo_ui7m.schema import UIAction class PlaywrightExecutor: """Execute LEO-UI7M UIAction objects on a Playwright sync Page.""" def __init__(self, page) -> None: self.page = page self.history: list[dict[str, Any]] = [] self.completed_ids: set[str] = set() def apply(self, action: UIAction, values: dict[str, str] | None = None) -> dict[str, Any]: values = values or {} data = action.to_dict() act = data["action"] eid = data.get("target_element_id") if act == "done": event = {"type": "done", "action": "done", "target_element_id": None} self.history.append(event) return {"ok": True, "event": event} if act == "wait": self.page.wait_for_timeout(100) event = {"type": "wait", "action": "wait", "target_element_id": None} self.history.append(event) return {"ok": True, "event": event} if not eid: return {"ok": False, "error": "missing_target_element_id", "action": data} loc = self.page.locator(f"#{eid}") if loc.count() < 1: return {"ok": False, "error": "target_not_found", "target_element_id": eid, "action": data} try: if act == "type": text = data.get("text") or values.get(eid, "") loc.fill(text) event = {"type": "type", "action": "type", "target_element_id": eid, "text": text} elif act == "select": value = data.get("value") or values.get(eid, "") loc.select_option(label=value) event = {"type": "select", "action": "select", "target_element_id": eid, "value": value} elif act == "click": if loc.get_attribute("type") == "checkbox": loc.check() else: loc.click() event = {"type": "click", "action": "click", "target_element_id": eid} else: return {"ok": False, "error": "unsupported_action", "action": data} except Exception as e: return {"ok": False, "error": type(e).__name__, "message": str(e), "action": data} self.completed_ids.add(eid) self.history.append(event) return {"ok": True, "event": event}