Skip to content

feat: auto-dismiss native dialogs in action helpers#316

Closed
edenowong wants to merge 1 commit intobrowser-use:mainfrom
edenowong:feat/auto-dismiss-dialogs
Closed

feat: auto-dismiss native dialogs in action helpers#316
edenowong wants to merge 1 commit intobrowser-use:mainfrom
edenowong:feat/auto-dismiss-dialogs

Conversation

@edenowong
Copy link
Copy Markdown

@edenowong edenowong commented May 6, 2026

Summary

Native dialogs (alert / confirm / prompt / beforeunload) freeze the JS thread, causing action helpers to silently hang behind a modal the agent never expected. The daemon already tracks pending dialogs via Page.javascriptDialogOpening, but helpers don't consult it. This PR makes action helpers auto-detect and dismiss after each action so a stray dialog doesn't deadlock the run.

Changes

  • New private helper _check_and_dismiss_dialog(accept=True, prompt_text="") in helpers.py. Reuses the existing _send({"meta": "pending_dialog"}) daemon channel that page_info() already uses.
  • Wraps four action helpers to auto-check after their CDP work:
    • goto_url (catches beforeunload)
    • click_at_xy
    • press_key
    • dispatch_key
  • Logs [auto-dismissed <type>] <message> per dismissal so runs are debuggable.
  • Opt out per process with BH_NO_AUTO_DISMISS=1 for callers that need to inspect dialogs manually (the existing API in interaction-skills/dialogs.md still works).
  • accept=True matches the JS-stub pattern in interaction-skills/dialogs.md (confirm returns true, beforeunload leaves).

Why

Currently agents get stuck on sites that throw an unexpected confirm() mid-flow (e.g. "Are you sure you want to leave?", form-validation alerts, beforeunload on navigation). The screenshot looks normal, the click coordinates are right, but every subsequent action silently no-ops because the JS thread is frozen. The fix is one CDP call (Page.handleJavaScriptDialog) — making it implicit in the action helpers eliminates an entire class of silent-hang failure mode.

Test plan

  • 9 new unit tests in test_dialog_auto_dismiss.py covering:
    • No-dialog path (no extra CDP call, no daemon round-trip when env-disabled)
    • Dialog present → Page.handleJavaScriptDialog called with correct args
    • accept=False and prompt_text= overrides
    • BH_NO_AUTO_DISMISS=1 opt-out
    • Integration through click_at_xy, press_key, goto_url
  • Full existing suite still passes (10 → 19 tests, all green)

Notes

  • The daemon already clears self.dialog on Page.javascriptDialogClosed (daemon.py:168), so there's no infinite-loop risk after dismissal.
  • Doesn't wrap type_text / scroll / upload_file — these don't typically trigger dialogs synchronously and the next action will catch any that slip through.
  • Manual API in interaction-skills/dialogs.md is unchanged; this only affects the default behavior of the wrapped helpers.

Summary by cubic

Auto-dismiss native alert/confirm/prompt/beforeunload dialogs after each action helper to prevent runs hanging behind unexpected modals. This makes interactions more reliable by unfreezing the JS thread automatically.

  • New Features
    • Added private _check_and_dismiss_dialog(accept=True, prompt_text="") that checks daemon pending_dialog and calls Page.handleJavaScriptDialog.
    • Auto-check added to goto_url, click_at_xy, press_key, and dispatch_key.
    • Logs [auto-dismissed <type>] <message> for debugging.
    • Opt out with BH_NO_AUTO_DISMISS=1 for manual dialog handling.

Written for commit af66c7c. Summary will update on new commits.

Native dialogs (alert/confirm/prompt/beforeunload) freeze the JS thread,
causing action helpers to hang silently — agent has no signal that the
run is stuck behind a modal it never expected. Daemon already tracks
pending dialogs via Page.javascriptDialogOpening; helpers now check
and dismiss after each action.

- _check_and_dismiss_dialog(accept=True, prompt_text="") — new helper
- goto_url, click_at_xy, press_key, dispatch_key — auto-check post-action
- BH_NO_AUTO_DISMISS=1 to opt out per process
- 9 unit tests covering all paths (dialog/no-dialog, accept t/f, prompt
  text, env opt-out, helper integration)

Manual API in interaction-skills/dialogs.md still works for callers
that need cancel-by-default or specific prompt responses.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

@edenowong edenowong closed this May 6, 2026
@edenowong edenowong deleted the feat/auto-dismiss-dialogs branch May 6, 2026 21:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant