diff --git a/src/fara/_prompts.py b/src/fara/_prompts.py index 09933f8..3506569 100644 --- a/src/fara/_prompts.py +++ b/src/fara/_prompts.py @@ -33,6 +33,7 @@ def description(self): * If a popup window appears that you want to close, if left_click() on the 'X' or close button doesn't work, try key(keys=['Escape']) to close it. * On some search bars, when you type(), you may need to press_enter=False and instead separately call left_click() on the search button to submit the search query. This is especially true of search bars that have auto-suggest popups for e.g. locations * For calendar widgets, you usually need to left_click() on arrows to move between months and left_click() on dates to select them; type() is not typically used to input dates there. +* If asked to monitor a page for changes, you can use wait() to pause for a while and avoid busy-waiting. You may need to follow that with refresh() to see the latest content. """.strip() parameters = { @@ -49,7 +50,8 @@ def description(self): * `web_search`: Perform a web search with a specified query. * `history_back`: Go back to the previous page in the browser history. * `pause_and_memorize_fact`: Pause and memorize a fact for future reference. -* `wait`: Wait specified seconds for the change to happen. +* `wait`: Wait specified number of seconds (e.g., for a page to load or a change to happen). +* `refresh`: Refresh the current webpage to update its content. * `terminate`: Terminate the current task and report its completion status. """.strip(), "enum": [ @@ -63,6 +65,7 @@ def description(self): "history_back", "pause_and_memorize_fact", "wait", + "refresh", "terminate", ], "type": "string", @@ -149,6 +152,8 @@ def call(self, params: Union[str, dict], **kwargs): return self._open(params["text"]) elif action == "wait": return self._wait(params["time"]) + elif action == "refresh": + return self._refresh() elif action == "terminate": return self._terminate(params["status"]) else: @@ -178,6 +183,9 @@ def _open(self, text: str): def _wait(self, time: int): raise NotImplementedError() + def _refresh(self): + raise NotImplementedError() + def _terminate(self, status: str): raise NotImplementedError() diff --git a/src/fara/browser/playwright_controller.py b/src/fara/browser/playwright_controller.py index 5ada7b3..279e56a 100644 --- a/src/fara/browser/playwright_controller.py +++ b/src/fara/browser/playwright_controller.py @@ -335,6 +335,12 @@ async def back(self, page: Page) -> None: await self._ensure_page_ready(page) await page.go_back() + @handle_target_closed() + async def refresh(self, page: Page) -> None: + await self._ensure_page_ready(page) + await page.reload() + await page.wait_for_load_state() + @handle_target_closed() async def visit_page(self, page: Page, url: str) -> Tuple[bool, bool]: await self._ensure_page_ready(page) diff --git a/src/fara/fara_agent.py b/src/fara/fara_agent.py index ab6b953..95d3bab 100644 --- a/src/fara/fara_agent.py +++ b/src/fara/fara_agent.py @@ -526,14 +526,16 @@ async def execute_action( if "coordinate" in args: tgt_x, tgt_y = args["coordinate"] await self._playwright_controller.hover_coords(self._page, tgt_x, tgt_y) - elif args["action"] == "sleep" or args["action"] == "wait": duration = args.get("duration", 3.0) duration = args.get("time", duration) action_description = ( - "I am waiting a short period of time before taking further action." + f"I am waiting {duration} seconds before taking further action." ) await self._playwright_controller.sleep(self._page, duration) + elif args["action"] == "refresh" or args["action"] == "reload": + action_description = "I refreshed the current page." + await self._playwright_controller.refresh(self._page) elif args["action"] == "click" or args["action"] == "left_click": if "coordinate" in args: tgt_x, tgt_y = args["coordinate"]