Repository navigation
Hold JavaScript dialogs open for the agent or the person to answer - #958
Merged
Merged
Conversation
omartelo
force-pushed
the
feat/browser-dialogs
branch
from
October 28, 2026 15:16
8f91c79 to
ae2a66d
Compare
omartelo
force-pushed
the
feat/browser-dialogs
branch
from
October 28, 2026 15:38
ae2a66d to
9c44545
Compare
…swers it A dialog the page opens now waits for an answer instead of freezing the page behind it for the 30 s pageWait. The agent's call that opened it answers at once with a dialog open: line, every other call on that page fails naming it, and browser_dialog (lich browser dialog) answers it, which the window plays as the agent's cursor pressing the card's button. The window shows it and answers through browser.Answer; a dialog the person answered reaches the agent's next page answer once. Accepting a beforeunload sooner than a second after it opened is held to that second: Chrome aborts the navigation it held and reloads the page otherwise (Chrome for Testing 155 and Helium 0.19.2.1, measured). The prose of the page answer moves into the prompt catalog; the line tags the tool descriptions name stay English.
The pane reads the dialog from the browser-state its store already keeps and draws it as a floating card at the top of the page: who says it, the message, a prompt's field with its default selected, and OK and Cancel (Leave and Stay on a beforeunload, OK alone on an alert). Enter accepts and Esc dismisses (an alert's Esc is OK too); the answer goes through browser.Answer. The agent's answer plays as its cursor pressing the card's button, in turn with its other actions, and the card stays until that press has played, though the state without the dialog arrives right after. Input the page refuses while it holds a dialog, and an answer the agent gave first, are not logged: the card is the answer.
A pane opened while a dialog held the page stayed black: laying the page out at the pane's size waits on the dialog for the whole pageWait, so the screencast never started. Resize now fails fast on a held page and lays it out once the dialog closes; the frames come meanwhile, at the size the page had (Chrome for Testing 155 and Helium, live test). The window's own calls on a held page now do nothing instead of failing, and the person answering a dialog the agent already answered is no error, so the window no longer recognizes those errors by their text (quietBrowserError and its test go with it). The agent cursor's queue keeps an answer to the dialog past its cap, so the card always waits for its press. The UI gallery shows the lit buttons.
lich browser info on a page holding a dialog told the reader to call browser_dialog, the MCP tool. The command line's page answer now names its own verb, lich browser dialog accept|dismiss, in every language.
omartelo
force-pushed
the
feat/browser-dialogs
branch
from
October 28, 2026 15:50
dec2d12 to
6445211
Compare
1 of 2 tasks
omartelo
added a commit
that referenced
this pull request
Oct 28, 2026
TestChromeAPaneOpenedOnADialogShowsThePage failed on every macos-latest run since #958: headless Chrome on macOS has not painted the page when Navigate returns, and a dialog held open before the first paint leaves the screencast no frame to send. The test asserted a frame of a page that was never drawn, which the contract never promised; a dialog opened by an agent's click comes after the page has been drawn. Measured on the runner: with the page drawn first (a screenshot, a prior screencast or two idle seconds) the held page casts within 25 ms; without, no frame in 15 s. The gap for a dialog opened before the first paint is written down in docs/ceilings.md.
omartelo
added a commit
that referenced
this pull request
Oct 28, 2026
…#965) TestChromeAPaneOpenedOnADialogShowsThePage failed on every macos-latest run since #958: headless Chrome on macOS has not painted the page when Navigate returns, and a dialog held open before the first paint leaves the screencast no frame to send. The test asserted a frame of a page that was never drawn, which the contract never promised; a dialog opened by an agent's click comes after the page has been drawn. Measured on the runner: with the page drawn first (a screenshot, a prior screencast or two idle seconds) the held page casts within 25 ms; without, no frame in 15 s. The gap for a dialog opened before the first paint is written down in docs/ceilings.md.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A JavaScript dialog froze the session browser. Measured before (Chromium 155, live test): a click on a button that calls
alert('hi')failed withcontext deadline exceededafter 30.0 s, and every read after it hung another 30.0 s. Nothing handledPage.javascriptDialogOpening.Now a dialog the page opens (alert, confirm, prompt, beforeunload) stays open until the agent or the person answers it:
dialog open:line. Any other call on that page fails, naming the dialog. The newbrowser_dialogtool (lich browser dialog accept|dismiss,textfor a prompt) answers it and returns the page after.dialog answered: confirm "Delete?" -> dismissed.beforeunload
Accepting a beforeunload sooner than about 450 ms after it opened makes Chromium abort the navigation it held (
net::ERR_ABORTEDabout a second in), reload the page and ask again. Measured on Chrome for Testing 155 and Helium 0.19.2.1: 3 of 3 aborted at 300 ms, 3 of 6 at 400 ms, none of 30 from 500 ms on. An accept is therefore held until one second after the dialog opened. An agent's or a person's answer already takes longer than that.Page answer language
The prose of a page answer now comes from the prompt catalog in all seven languages: the element-list legend, the filled and checked marks, the more-below note, a running download, a timed-out wait, the count of further console errors, and what an open dialog asks of the agent. The line tags the tool descriptions name (
url:,text:,downloaded:,console error:,dialog open:and the rest) stay English.pageTexttakes the language. That is why the existingpageTexttests gained aprompt.Englishargument; no assertion changed.Notes
browser.AnswerDialog(agent, returns the page) andbrowser.Answer(window);BrowserState.Dialog,BrowserPageInfo.DialogandDialogs; agent actsacceptanddismiss.contract.goldenis updated.runnow fails witherrDialogOpenat once while a dialog is open, and as soon as one opens during a call. Calls that do not touch the page's script (screencast acks, resize, cookies, focus, the answer itself) go throughrunFree.TestMCPListsEveryToolgainedbrowser_dialog, because the tool list is the contract.Emulation.setDeviceMetricsOverrideandPage.captureScreenshotwait on the dialog (measured on both browsers). A pane opened during a dialog therefore starts its screencast at the page's current size, which still draws, and lays the page out once the dialog closes. Before, the pane stayed black. Screenshots fail until the dialog is answered.Litbutton state.Test plan
TestChromeADialogWaitsForTheAgentsAnswer(live): alert, confirm (dismiss), prompt (custom text) and leaving through a beforeunload. 5 of 5 runs on Helium and on Chrome for Testing 155.pageTextin every language; the CLI verb and the MCP tool.TestChromeAPaneOpenedOnADialogShowsThePage(live): a screencast started on a held page delivers a frame at once, and the page takes the pane's width after the answer. 5 of 5 on both browsers.gofmt,go vet ./...,go test ./...green for the backend and fornative/.