diff --git a/skyvern/forge/sdk/routes/streaming/channels/exfiltration.py b/skyvern/forge/sdk/routes/streaming/channels/exfiltration.py index b76cefc5..16be326c 100644 --- a/skyvern/forge/sdk/routes/streaming/channels/exfiltration.py +++ b/skyvern/forge/sdk/routes/streaming/channels/exfiltration.py @@ -89,6 +89,16 @@ class ExfiltrationChannel(CdpChannel): self.on_event(messages) + if event_name in ("frame_navigated", "navigated_within_document"): + # optimistically re-apply exfiltration and decoration on navigation + # (these operations should be idempotent) + pages = self.browser_context.pages if self.browser_context else [] + LOG.info(f"{self.class_name} re-applying exfiltration and decoration on navigation.", event_name=event_name) + + for page in pages: + asyncio.create_task(self.exfiltrate(page)) + asyncio.create_task(self.decorate(page)) + async def connect(self, cdp_url: str | None = None) -> t.Self: if self.browser and self.browser.is_connected() and self.cdp_session: return self diff --git a/skyvern/forge/sdk/routes/streaming/channels/js/decorate.js b/skyvern/forge/sdk/routes/streaming/channels/js/decorate.js index 1228d77c..55cb2a67 100644 --- a/skyvern/forge/sdk/routes/streaming/channels/js/decorate.js +++ b/skyvern/forge/sdk/routes/streaming/channels/js/decorate.js @@ -4,6 +4,14 @@ window.__skyvern_create_mouse_follower = function () { // create the circle element + const existingCircle = document.getElementById( + "__skyvern_mouse_follower", + ); + + if (existingCircle) { + return false; + } + const circle = document.createElement("div"); window.__skyvern_decoration_mouse_follower = circle; circle.id = "__skyvern_mouse_follower"; @@ -18,9 +26,15 @@ circle.style.zIndex = "999999"; circle.style.willChange = "transform"; document.body.appendChild(circle); + + return true; }; - window.__skyvern_create_mouse_follower(); + const wasCreated = window.__skyvern_create_mouse_follower(); + + if (!wasCreated) { + return; + } let scale = 1; let targetScale = 1;