Compare commits

...

1 Commits

Author SHA1 Message Date
Nikhil Sonti
7eb87458da fix: use CDP selectAll command for cross-platform field clearing
clearField() used Control+A to select all text before deleting, but on
macOS Chrome, Ctrl+A is the Emacs "beginning of paragraph" binding — not
select-all. This meant the clear tool never actually cleared field content.

Use CDP's `commands: ['selectAll']` parameter on dispatchKeyEvent to trigger
the browser's editing command directly, bypassing platform-specific keyboard
shortcut mappings. Also adds a dedicated Browser.clear() method so the clear
tool no longer routes through fill() with an empty string.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 18:08:12 -07:00
3 changed files with 29 additions and 13 deletions

View File

@@ -821,6 +821,22 @@ export class Browser {
return coords
}
async clear(page: number, element: number): Promise<void> {
const session = await this.resolveSession(page)
await elements.scrollIntoView(session, element)
try {
await elements.focusElement(session, element)
} catch {
try {
const { x, y } = await elements.getElementCenter(session, element)
await mouse.dispatchClick(session, x, y, 'left', 1, 0)
} catch {
logger.warn('Could not focus element for clear')
}
}
await keyboard.clearField(session)
}
async pressKey(page: number, key: string): Promise<void> {
const session = await this.resolveSession(page)
await keyboard.pressCombo(session, key)

View File

@@ -180,31 +180,31 @@ export async function typeText(
}
export async function clearField(session: ProtocolApi): Promise<void> {
// Use the CDP `commands` parameter to trigger the selectAll editing command
// directly, bypassing platform-specific keyboard shortcut mappings
// (Ctrl+A doesn't select all on macOS Chrome — it's the Emacs "beginning of paragraph" binding)
await session.Input.dispatchKeyEvent({
type: 'keyDown',
type: 'rawKeyDown',
key: 'a',
code: 'KeyA',
modifiers: 2,
windowsVirtualKeyCode: 65,
commands: ['selectAll'],
})
await session.Input.dispatchKeyEvent({
type: 'keyUp',
key: 'a',
code: 'KeyA',
modifiers: 2,
windowsVirtualKeyCode: 65,
})
await session.Input.dispatchKeyEvent({
type: 'keyDown',
key: 'Delete',
code: 'Delete',
windowsVirtualKeyCode: 46,
type: 'rawKeyDown',
key: 'Backspace',
code: 'Backspace',
windowsVirtualKeyCode: 8,
})
await session.Input.dispatchKeyEvent({
type: 'keyUp',
key: 'Delete',
code: 'Delete',
windowsVirtualKeyCode: 46,
key: 'Backspace',
code: 'Backspace',
windowsVirtualKeyCode: 8,
})
}

View File

@@ -177,7 +177,7 @@ export const clear = defineTool({
element: z.number(),
}),
handler: async (args, ctx, response) => {
await ctx.browser.fill(args.page, args.element, '', true)
await ctx.browser.clear(args.page, args.element)
response.text(`Cleared [${args.element}]`)
response.data({ action: 'clear', page: args.page, element: args.element })
response.includeSnapshot(args.page)