fix(browser): restore prompt submission when the Chrome window is hidden (#298)#302
fix(browser): restore prompt submission when the Chrome window is hidden (#298)#302LeoLin990405 wants to merge 1 commit into
Conversation
Since steipete#282 the send button is activated with trusted CDP input events at viewport coordinates (Input.dispatchMouseEvent), with the synthetic DOM click demoted to a last-resort path for buttons without a usable rect. Chrome delivers trusted input only to a composited window, so a hidden (--browser-hide-window), minimized, or occluded window swallows the click. attemptSendButton still reports success, promptSubmitted is set, and the run then fails in commit verification with 'Prompt did not appear in conversation before timeout'. 0.15.0 was unaffected because it always used the DOM click. Two changes: 1. Enable Emulation.setFocusEmulationEnabled on the local browser path, so the page behaves like a foreground tab. This already guards the remote path (steipete#289); factor it into a shared enableFocusEmulation helper used by both. 2. Stop trusting the trusted click blindly. After dispatching it, confirm the send actually left the composer (composer cleared / send button gone / stop button / assistant turn); if it clearly did not, fall back to the synthetic DOM click that worked before steipete#282. The fallback re-queries for a visible and *enabled* send button, so a slow-but-successful send cannot be sent twice. Live A/B on macOS with --browser-hide-window (copy-profile, gpt-5.5-pro): - before: 'Clicked send button' then commit-timeout; commitProbe shows the full prompt still in the composer, turnsCount 0, url never leaves chatgpt.com/ - after: 'Focus emulation enabled for local target' -> send commits -> /c/<id> conversation -> answer captured in 25.1s Fixes steipete#298
|
Codex review: needs changes before merge. Reviewed July 10, 2026, 5:43 AM ET / 09:43 UTC. Summary Reproducibility: yes. The PR supplies a controlled current-main failure and branch success for hidden-window submission, and source inspection establishes a deterministic false-positive path when a conversation already contains assistant messages. Review metrics: 2 noteworthy metrics.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Copy recommended automerge instructionNext step before merge
Security Review findings
Review detailsBest possible solution: Retain the proven local focus-emulation fix, but compare post-click state with a pre-click baseline so the fallback fires exactly once when no new submission transition occurs. Do we have a high-confidence way to reproduce the issue? Yes. The PR supplies a controlled current-main failure and branch success for hidden-window submission, and source inspection establishes a deterministic false-positive path when a conversation already contains assistant messages. Is this the best way to solve the issue? No, not yet. Focus emulation is the narrow proven fix, but the fallback must detect a new attributable state transition rather than treating historical assistant content as success. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against f3fbc067c9d8. Label changesLabel changes:
Label justifications:
Evidence reviewedAcceptance criteria:
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
Fixes #298. The reporter's hypothesis was right, and this pins it to a specific commit with a live A/B.
Root cause (bisected to #282)
clickTrustedPoint— CDPInput.dispatchMouseEventat viewport coordinates — was introduced bybcb835b(#282, "preserve Deep Research selection through submit").git tag --contains bcb835b→v0.15.1, which is exactly the reporter's regression window (0.15.0 good, 0.15.2 bad).That commit also demoted the old synthetic DOM click to a comment-documented "last-resort fallback for unusual DOMs where the button is visible but has no useful rect". Since a real send button always has a rect, every send in 0.15.1+ now takes the trusted-click path.
Chrome delivers trusted input events only to a window that is being composited.
--browser-hide-windowhides the whole app via AppleScript (set visible ... to false), so the click is swallowed. Nothing errors:attemptSendButtonreturnstrue,promptSubmittedis set, and the run dies later in commit verification withPrompt did not appear in conversation before timeout— withtabUrlstill at barehttps://chatgpt.com/, exactly as reported.This is the same failure mode I hit on the remote path in #289 (occluded window → send dropped); the local path never got the corresponding guard.
Live A/B (macOS,
--copy-profile,gpt-5.5-pro[browser], no attachments)Single variable:
--browser-hide-window.Current
main, hidden window — reproduced:The prompt is still sitting in the composer — the click never landed. (Same command with a visible window: answer captured in 21.0s.)
This branch, hidden window — fixed:
Changes
Enable focus emulation on the local path.
Emulation.setFocusEmulationEnabledmakes the page behave like a foreground tab. The remote path already does this (fix(browser): recover remote Chrome sessions reliably #289); this factors it into a sharedenableFocusEmulation(client, logger, label)helper used by both, and soft-fails with a log line if the target rejects it.Stop trusting the trusted click blindly. After dispatching it,
sendTookEffectconfirms the send actually left the composer (composer cleared / send button gone / stop button visible / assistant turn present, polled up to 1.5s). If it clearly did not, fall back to the synthetic DOM click that worked before fix(browser): preserve Deep Research selection through submit #282. The fallback re-queries for a visible and enabled send button — after a successful send there isn't one, so a slow-but-successful send cannot be submitted twice.(1) alone fixes the reported case; (2) is defense in depth for any environment where trusted input cannot land (and restores 0.15.0's behavior as the floor rather than failing the run).
Answering the reporter's questions
--browser-hide-windowis opt-in, so simply omitting it keeps the window visible; there is no--no-browser-hide-windowbecause the default is alreadyfalse. Worth noting the reported session had it on.commitProbeit added is what made this diagnosable at a glance.Checks
pnpm run checkclean;pnpm vitest run— 1421 passed, 43 skipped, 0 failed.sendTookEffectpositive/negative,dispatchSendButtonClickpresent/absent button, and bothattemptSendButtonbranches (fallback fires when swallowed; fallback does not fire when the trusted click landed).