fix(dialog): let agents decide native JavaScript dialogs - #379
Open
NianJiuZst wants to merge 1 commit into
Open
NianJiuZst wants to merge 1 commit into
NianJiuZst wants to merge 1 commit into
Conversation
NianJiuZst
force-pushed
the
codex/js-dialog-agent-control
branch
from
September 30, 2026 07:56
f488ab1 to
d928da3
Compare
This branch has not been deployed
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.
A native
confirm("Delete all 200 test rows?")currently accepts automatically, so the page proceeds without an agent decision. Prompts and beforeunload dialogs have the same forced-accept behavior. This change lets the agent inspect the pending dialog, accept or dismiss it, supply prompt input, and obtain the original action's result without executing the action again.Fixes #359.
How it works
alert,confirm,prompt,beforeunload) with a dialog ID, type, message, bounded default preview, attachment identity, and decision deadline. Record Chrome's actual closing event rather than assuming the requested decision succeeded.dialog status/accept/dismisson a same-session control path that bypasses the busy action queue and renderer-dependent preparation/debug screenshots. Changing an auto-accept default alone would leave a sequential agent unable to answer the modal while its original call blocks.dialog_pending(CLI exit 6) with an originaloperation_id. Keep the complete dispatched operation, busy/inflight ownership, audit, and transfer postprocessing alive.operation awaitretrieves its original success or failure; chained dialogs retain that operation ID. It never repeats the click/evaluation/navigation.browser_assisttool and preserve pending IDs in model-facing errors. CLI and DSH skills tell the agent to decide from the requested workflow, including choosing input/confirmation, without turning each native dialog into human request-help.dispatched: false.--text ""remains empty input. Handle beforeunload dismissal as a cancelled navigation that keeps the current page, including Chrome'sERR_ABORTEDevent ordering.Requires matching protocol 1.4 components. The updated extension rejects daemons older than 1.4. Unanswered dialogs reject after 60 seconds and fail the original operation. Receipts are bounded to 64 slots, 4 MiB per result, and up to five minutes from completion; completed receipts can be evicted at capacity. Cancellation cannot undo page effects already dispatched.
Real browser verification
Passed on macOS ARM64 / Chrome for Testing 153.0.8010.12, at 2026-09-30 07:26:39 UTC. Tested implementation:
d928da30e9e00e8ef613adaf9fc4f5e6b83b6265.The runner launches a visible browser with a fresh profile, production MV3 extension, and a private daemon. Every dialog answer uses the actual CLI → daemon IPC → extension WebSocket → chrome.debugger path. Remote CDP is only used for browser setup/metadata; it never answers a dialog. Debug capture remains enabled while the native modal is pending.
false; retrieving twice leaves the invocation counter at oneAgent-selected name""/nullanonymous, and all 10,000 characters of a long defaultcancelledfailure remains retrievableReproduction instructions.
For example, these commands in the recorded run supplied custom prompt input and retrieved the original value:
Screenshots from that run
Unedited OS captures of the isolated test window. A modal can defer repainting the counters behind it; state assertions run after closure.
Pending confirm before a decision:
Pending prompt before supplying input:
Page results after dismissal, a separately accepted click, and custom input:
Local checks
cargo test --workspace --locked: 837 passed, 0 failed, 1 ignored across 46 targets, including a real daemon IPC/WS regression with a controlled extension peer.cargo fmt --all -- --checkandcargo clippy --workspace --all-targets --locked -- -D warnings: passed. A test-only owned-vector iteration cleanup in the updater avoids the current Rust redundant-clone lint; updater runtime behavior is unchanged.pnpm --filter @browser-skill/extension test: 2,440 passed, 122 skipped; compile and production build passed.BSK_DIALOG_TEST_TIMEOUT=1, including the actual 60-second fallback.The real-browser cases use predetermined decisions to verify available controls and continuation; they are not an LLM decision-quality benchmark. DSH model-facing routing has separate plugin tests. Hosted CI and Windows behavior are reported by the PR checks separately.