fix(browser): preserve chat focus during agent browsing

This commit is contained in:
2026-09-27 15:23:23 +08:00
parent 220e89992b
commit a52e747a00
10 changed files with 323 additions and 16 deletions

View File

@@ -20,7 +20,7 @@ function isAllowedTopLevelUrl(value: string): boolean {
}
}
function wrapDebugger(contents: WebContents): AgentBrowserDebuggerPort {
function wrapDebugger(contents: WebContents, isVisible: () => boolean): AgentBrowserDebuggerPort {
const debuggerEvents = contents.debugger as unknown as {
on(event: string, listener: PortListener): void;
removeListener(event: string, listener: PortListener): void;
@@ -29,8 +29,14 @@ function wrapDebugger(contents: WebContents): AgentBrowserDebuggerPort {
attach: (version) => contents.debugger.attach(version),
detach: () => contents.debugger.detach(),
isAttached: () => contents.debugger.isAttached(),
sendCommand: (method, params, sessionRef) =>
contents.debugger.sendCommand(method, params, sessionRef),
sendCommand: async (method, params, sessionRef) => {
if (method === 'Page.captureScreenshot' && !isVisible()) {
// CDP capture can wait forever for a hidden view's compositor. Electron's
// native capture requests a frame without showing or focusing the view.
await contents.capturePage(undefined, { stayHidden: true, stayAwake: false });
}
return contents.debugger.sendCommand(method, params, sessionRef);
},
on: (event, listener) => debuggerEvents.on(event, listener),
removeListener: (event, listener) =>
debuggerEvents.removeListener(event, listener),
@@ -53,13 +59,13 @@ function wrapNavigation(contents: WebContents): AgentBrowserNavigationPort {
};
}
function wrapWebContents(contents: WebContents): AgentBrowserWebContentsPort {
function wrapWebContents(contents: WebContents, isVisible: () => boolean): AgentBrowserWebContentsPort {
const contentsEvents = contents as unknown as {
on(event: string, listener: PortListener): void;
removeListener(event: string, listener: PortListener): void;
};
return {
debugger: wrapDebugger(contents),
debugger: wrapDebugger(contents, isVisible),
navigationHistory: wrapNavigation(contents),
loadURL: (url) => contents.loadURL(url),
getURL: () => contents.getURL(),
@@ -111,7 +117,7 @@ export class ElectronAgentBrowserAdapter implements AgentBrowserAdapter {
this.guardSession(contents.session);
const view: AgentBrowserViewPort = {
webContents: wrapWebContents(contents),
webContents: wrapWebContents(contents, () => nativeView.getVisible()),
setBounds: (bounds: AgentBrowserBounds) =>
nativeView.setBounds(this.toNativeBounds(bounds)),
setVisible: (visible: boolean) => nativeView.setVisible(visible),