fix(browser): stop raw exec commands from opening the system file picker (#41344)

This commit is contained in:
Kelvin Amoaba
2026-11-12 04:49:47 +00:00
committed by GitHub
parent c5e82a637d
commit 5bc83d98db
5 changed files with 18 additions and 8 deletions
@@ -278,7 +278,8 @@ export class AgentBrowserBridge extends AgentBrowserBridgeInteractionCommands {
worktreeId,
browserPageId,
async (sessionName) => await this.execAgentBrowser(sessionName, args, { cliArgv: true }),
{ elements: passthroughElementArgs(args) }
// Raw commands and batches can click or press keys too.
{ elements: passthroughElementArgs(args), blockFileChooser: true }
)
}
}
@@ -108,6 +108,13 @@ describe('an agent click that opens a file picker', () => {
expect(intercepting).toBe(false)
})
it('catches the picker a raw exec click opens', async () => {
await expect(bridge.exec('click @e3')).rejects.toMatchObject({
code: 'browser_file_chooser_opened'
})
expect(intercepting).toBe(false)
})
it("stops intercepting the desktop user's pickers when an SSH host loses the page mid-click", async () => {
const revoked = new AbortController()
onClick = () => revoked.abort()
@@ -72,7 +72,8 @@ export abstract class AgentBrowserBridgeQueue extends AgentBrowserBridgeActionEf
): Promise<T> {
return this.enqueueTargetedCommand(worktreeId, browserPageId, execute, {
...options,
reportEffects: options.reportEffects !== false
reportEffects: options.reportEffects !== false,
blockFileChooser: options.blockFileChooser !== false
})
}
@@ -85,7 +86,7 @@ export abstract class AgentBrowserBridgeQueue extends AgentBrowserBridgeActionEf
): Promise<T> {
return this.enqueuePageAction(worktreeId, browserPageId, execute, {
...options,
skipFileChooserBlock: true
blockFileChooser: false
})
}
@@ -117,8 +118,8 @@ export abstract class AgentBrowserBridgeQueue extends AgentBrowserBridgeActionEf
const inThisCall = captureActiveRpcCall()
// Decided at enqueue: a queued command runs under the caller of the command ahead of it.
const reportEffects = options.reportEffects === true && agentCommand.agent
// Page actions deliver agent or remote input; a desktop picker would activate Orca over the user's work.
const blockFileChooser = options.reportEffects === true && options.skipFileChooserBlock !== true
// A desktop picker would activate Orca over the user's work.
const blockFileChooser = options.blockFileChooser === true
const expectedUrl = getRequestedPageUrl()
// A dialog blocks the page until it is answered. A command still waiting never runs; one
@@ -8,8 +8,9 @@ export type EnqueueTargetedCommandOptions = {
ensureSession?: boolean
/** Page actions report what they caused when an agent runs them. */
reportEffects?: boolean
// Upload catches the picker itself; actions without user activation cannot open one.
skipFileChooserBlock?: boolean
// Agent or remote input must not raise the OS file picker. Upload catches the picker itself, and
// actions without user activation cannot open one.
blockFileChooser?: boolean
// Text mutations must not fall back to a global tab from another worktree.
requireScopedTarget?: boolean
// Element arguments that may be snapshot refs.
@@ -115,7 +115,7 @@ export abstract class AgentBrowserBridgeInteractionCommands extends AgentBrowser
await chooser.release()
}
},
{ elements: [element], skipFileChooserBlock: true }
{ elements: [element], blockFileChooser: false }
)
}