Add BH_NO_FOCUS so tab operations don't raise the browser window - #587
Open
vibrant wants to merge 1 commit into
Open
Add BH_NO_FOCUS so tab operations don't raise the browser window#587vibrant wants to merge 1 commit into
vibrant wants to merge 1 commit into
Conversation
Target.activateTarget activates the whole application on macOS, so every
new_tab()/switch_tab() steals keyboard focus from the terminal driving the
run. With BH_NO_FOCUS=1, tabs are created with Target.createTarget's
background flag and activation is skipped; the harness still attaches to and
drives the tab, it just isn't the visibly-selected one.
Unset (the default) behaviour is unchanged. switch_tab(tid, activate=True)
and an explicit cdp("Target.activateTarget", ...) remain the way to show a
tab on purpose.
✅ Skill review passedReviewed 1 file(s) — no findings. |
Contributor
There was a problem hiding this comment.
1 issue found across 3 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/browser_harness/helpers.py">
<violation number="1" location="src/browser_harness/helpers.py:344">
P2: Default `new_tab()` now sends the optional `background` parameter even when no-focus mode is disabled, which can break headless-shell CDP endpoints where that parameter is unsupported. Preserve the old call when `_no_focus()` is false and add `background=True` only for the opt-in path.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
| except Exception: | ||
| pass | ||
| tid = cdp("Target.createTarget", url="about:blank")["targetId"] | ||
| tid = cdp("Target.createTarget", url="about:blank", background=_no_focus())["targetId"] |
Contributor
There was a problem hiding this comment.
P2: Default new_tab() now sends the optional background parameter even when no-focus mode is disabled, which can break headless-shell CDP endpoints where that parameter is unsupported. Preserve the old call when _no_focus() is false and add background=True only for the opt-in path.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/browser_harness/helpers.py, line 344:
<comment>Default `new_tab()` now sends the optional `background` parameter even when no-focus mode is disabled, which can break headless-shell CDP endpoints where that parameter is unsupported. Preserve the old call when `_no_focus()` is false and add `background=True` only for the opt-in path.</comment>
<file context>
@@ -323,7 +341,7 @@ def new_tab(url="about:blank"):
except Exception:
pass
- tid = cdp("Target.createTarget", url="about:blank")["targetId"]
+ tid = cdp("Target.createTarget", url="about:blank", background=_no_focus())["targetId"]
switch_tab(tid)
if url != "about:blank":
</file context>
Suggested change
| tid = cdp("Target.createTarget", url="about:blank", background=_no_focus())["targetId"] | |
| create_params = {"url": "about:blank"} | |
| if _no_focus(): | |
| create_params["background"] = True | |
| tid = cdp("Target.createTarget", **create_params)["targetId"] |
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.
Problem
Target.activateTargetactivates the whole application on macOS, not just the window.switch_tab()calls it unconditionally andnew_tab()callsswitch_tab(), so every tab the harness opens steals keyboard focus from the terminal driving the run. For long agent runs on a desktop that makes the machine unusable — you get yanked out of whatever you were typing every few seconds.Change
Opt-in
BH_NO_FOCUS=1:new_tab()passesbackground=TruetoTarget.createTargetswitch_tab()skipsTarget.activateTargetTarget.createTargetis backgrounded tooThe harness still attaches to and drives the right tab — activation only controls which tab is visibly selected.
switch_tab(tid, activate=True)and an explicitcdp("Target.activateTarget", targetId=tid)remain the way to show a tab on purpose;interaction-skills/tabs.mdis updated to say so.Default behaviour is unchanged when the variable is unset.
Notes
Pairs well with launching Chrome via
open -gon macOS, plus--disable-backgrounding-occluded-windows --disable-renderer-backgrounding --disable-background-timer-throttling— without those an occluded window stops producing frames and throttles timers.Verification
macOS 26.5, Chrome 151, dedicated automation profile:
new_tab()calls plus aswitch_tab()withBH_NO_FOCUS=1— frontmost app never changed; withBH_NO_FOCUS=0it changed to Chrome as beforecapture_screenshot()on a never-activated tab renders the page correctly (not blank)setInterval(…, 10)on a never-activated tab: 300 ticks in 3s, i.e. unthrottledpytest tests/unit— 97 passedSummary by cubic
Add an opt-in BH_NO_FOCUS=1 mode to stop tab operations from raising the Chrome window, so long runs don’t steal focus from the terminal on macOS. Tabs open in the background and activation is skipped; default behavior is unchanged.
new_tab()usesTarget.createTargetwithbackground=Truewhen BH_NO_FOCUS=1.switch_tab(target, activate=None)skipsTarget.activateTargetby default when BH_NO_FOCUS=1; useswitch_tab(tid, activate=True)orcdp("Target.activateTarget", ...)to show a tab.backgroundunder BH_NO_FOCUS.Written for commit 9f50d2e. Summary will update on new commits.