mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-14 05:37:40 +02:00
44 lines
2.1 KiB
TypeScript
44 lines
2.1 KiB
TypeScript
import type { BrowserWebview } from './browserRegistry';
|
|
|
|
// A synthetic key or text insert follows the HOST window's focus, not the CDP target it was
|
|
// addressed to. Measured in an isolated Electron probe, with the user's caret in a plain input:
|
|
//
|
|
// Input.dispatchKeyEvent -> the characters landed in the USER's input, not the page
|
|
// Input.insertText -> a whole string landed in the USER's input, not the page
|
|
// after focusing the <webview> element first -> both landed in the page, user's input untouched
|
|
//
|
|
// So the guest MUST hold host focus while the agent types, and the previously trusted in-guest
|
|
// document.body.focus() does not provide it (same probe, still leaked). This is also why the
|
|
// caret-restore idea in ENG-252 is not merely useless but harmful: hand the caret back mid-run and
|
|
// the agent's next Enter submits whatever the user was halfway through writing.
|
|
|
|
let p_takeovers = 0;
|
|
|
|
/** How many times a keystroke had to take the caret off a real user text surface. */
|
|
export function guestKeyTakeoverCount(): number {
|
|
return p_takeovers;
|
|
}
|
|
|
|
export function resetGuestKeyTakeoverCount(): void {
|
|
p_takeovers = 0;
|
|
}
|
|
|
|
function p_isUserTextSurface(el: Element | null): boolean {
|
|
if (!el) return false;
|
|
return el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || (el as HTMLElement).isContentEditable === true;
|
|
}
|
|
|
|
/** Give the guest the host focus its keystrokes need, counting when we took it from a user. */
|
|
export function focusGuestForKeys(wv: BrowserWebview): void {
|
|
const before = typeof document !== 'undefined' ? document.activeElement : null;
|
|
if (before !== (wv as unknown as Element) && p_isUserTextSurface(before)) p_takeovers += 1;
|
|
try {
|
|
// A docked browser is parked far off-canvas, and a bare focus() is allowed to scroll its target
|
|
// into view. Measured harmless at left:-100000 (negative clamps to 0), but not for a card parked
|
|
// the other way, and refusing the scroll costs nothing: keys still land in a parked guest.
|
|
wv.focus({ preventScroll: true });
|
|
} catch {
|
|
// The card unmounted mid-command. The keystroke will miss, which beats it hitting the user.
|
|
}
|
|
}
|