From 5404bb7cdbfd25152f4468a68370444765cdae70 Mon Sep 17 00:00:00 2001 From: Michael Rowlinson Date: Fri, 20 Feb 2026 19:30:34 -0800 Subject: [PATCH] fix: update UI selectors and submission for current AI Studio Google AI Studio updated its Angular UI, breaking the existing selectors and submission flow. This patch fixes three issues: 1. Submit button selector: Added 'button.ctrl-enter-submits' to match the current AI Studio submit button class. 2. Text input method: Replaced JavaScript element.value assignment with Playwright's native fill() method. The JS approach bypassed Angular's reactive forms change detection, leaving the internal model empty despite text being visually present. 3. Submission method: Replaced the submit button click + tooltip dismissal flow with Meta+Enter keyboard shortcut. The tooltip dismissal (_dismiss_tooltip_overlays) was hanging indefinitely on the current UI, and Meta+Enter is more reliable as it bypasses button state checks entirely. Tested on macOS with Camoufox v135.0.1-beta.24. --- browser_utils/page_controller.py | 74 +++----------------------------- config/selectors.py | 8 ++++ 2 files changed, 14 insertions(+), 68 deletions(-) diff --git a/browser_utils/page_controller.py b/browser_utils/page_controller.py index 38c3dda0..d4b4e47b 100644 --- a/browser_utils/page_controller.py +++ b/browser_utils/page_controller.py @@ -153,76 +153,14 @@ async def submit_prompt( ) # Fill textarea using centralized logic (inherited from InputController if possible, or direct) - await textarea.evaluate( - "(el, t) => { el.value = t; el.dispatchEvent(new Event('input', {bubbles:true})); el.dispatchEvent(new Event('change', {bubbles:true})); }", - prompt, - ) - await self._check_disconnect( - check_client_disconnected, "After Input Fill" - ) - - if image_list: - await self._open_upload_menu_and_choose_file(image_list) - - # Wait for submit button to be enabled - submit = self.page.locator(SUBMIT_BUTTON_SELECTOR) - button_clicked = False - is_btn_enabled = False - try: - await expect_async(submit).to_be_enabled(timeout=10000) - is_btn_enabled = True - except Exception: - self.logger.warning( - f"[{self.req_id}] Submit button not enabled within timeout, trying keyboard fallback." - ) - + # Playwright fill + keyboard submit (patched) + await textarea.click() + await textarea.fill(prompt) + await asyncio.sleep(0.3) + await textarea.press("Meta+Enter") await self._check_disconnect( - check_client_disconnected, "After Submit Button Check" + check_client_disconnected, "After Submit" ) - - if is_btn_enabled: - try: - # Defensive workarounds before click: handle dialogs, backdrops and tooltips - await self._handle_post_upload_dialog() - await self._dismiss_backdrops() - if hasattr(self, "_dismiss_tooltip_overlays"): - await self._dismiss_tooltip_overlays() - - await submit.click(timeout=5000) - button_clicked = True - self.logger.info(f"[{self.req_id}] Submit button clicked.") - await check_quota_limit(self.page, self.req_id) - except QuotaExceededError: - raise - except Exception as click_err: - self.logger.warning( - f"[{self.req_id}] Button click failed: {click_err}. Trying keyboard fallback." - ) - - if not button_clicked: - # Keyboard fallbacks (using logic inherited from InputController) - self.logger.info( - f"[{self.req_id}] Attempting Enter key submission..." - ) - if await self._try_enter_submit( - textarea, check_client_disconnected - ): - button_clicked = True - else: - self.logger.info( - f"[{self.req_id}] Attempting Combo key submission..." - ) - if await self._try_combo_submit( - textarea, check_client_disconnected - ): - button_clicked = True - - if not button_clicked: - raise Exception( - "Failed to submit prompt via button or keyboard shortcuts." - ) - - await self._check_disconnect(check_client_disconnected, "After Submit") return except QuotaExceededError: raise diff --git a/config/selectors.py b/config/selectors.py index 1d90d33d..21bd7936 100644 --- a/config/selectors.py +++ b/config/selectors.py @@ -296,3 +296,11 @@ 'mat-dialog-container button:has-text("Cancel"), ' 'mat-mdc-dialog-container button:has-text("Cancel")' ) + +# Patched: add new AI Studio submit button class +SUBMIT_BUTTON_SELECTOR = ( + "button.ctrl-enter-submits, " + "ms-run-button button[type=\"submit\"].ms-button-primary, " + "ms-run-button button[type=\"submit\"], " + 'button[aria-label="Run"][type="submit"]' +)