feat(extension): auto-close automation window after command completes

- Add 'close-window' action to extension protocol and background.ts
- Add Page.closeWindow() method to send close-window command
- browserSession() now closes automation window in cleanup
- Remove domain pre-navigation + 2s wait from main.ts (CDP handles
  cross-domain cookies natively, no same-origin workaround needed)
- Net effect: commands run faster, no stale windows left behind
This commit is contained in:
jackwener committed 2026-03-19 23:59:31 +08:00
1 parent fde618063f
commit 2f6d28a3e9
7 files changed
+46 -13

No files matched your search

+1 -1
View File
@@ -15,7 +15,7 @@ function generateId(): string {
export interface DaemonCommand {
id: string;
action: 'exec' | 'navigate' | 'tabs' | 'cookies' | 'screenshot';
action: 'exec' | 'navigate' | 'tabs' | 'cookies' | 'screenshot' | 'close-window';
tabId?: number;
code?: string;
url?: string;
+9
View File
@@ -37,6 +37,15 @@ export class Page implements IPage {
}
}
/** Close the automation window in the extension */
async closeWindow(): Promise<void> {
try {
await sendCommand('close-window', {});
} catch {
// Window may already be closed or daemon may be down
}
}
async evaluate(js: string): Promise<any> {
const code = wrapForEval(js);
return sendCommand('exec', { code, ...this._tabOpt() });
-6
View File
@@ -193,12 +193,6 @@ for (const [, cmd] of registry) {
let result: any;
if (cmd.browser) {
result = await browserSession(BrowserBridge, async (page) => {
// Cookie/header strategies require same-origin context for credentialed fetch.
// In CDP mode the active tab may be on an unrelated domain, causing CORS failures.
// Navigate to the command's domain first (mirrors cascade command behavior).
if ((cmd.strategy === Strategy.COOKIE || cmd.strategy === Strategy.HEADER) && cmd.domain) {
try { await page.goto(`https://${cmd.domain}`); await page.wait(2); } catch {}
}
return runWithTimeout(executeCommand(cmd, page, kwargs, actionOpts.verbose), { timeout: cmd.timeoutSeconds ?? DEFAULT_BROWSER_COMMAND_TIMEOUT, label: fullName(cmd) });
});
} else { result = await executeCommand(cmd, null, kwargs, actionOpts.verbose); }
+7 -5
View File
@@ -1,8 +1,5 @@
/**
* Runtime utilities: timeouts and browser session management.
*/
import type { IPage } from './types.js';
import type { Page } from './browser/page.js';
export const DEFAULT_BROWSER_CONNECT_TIMEOUT = parseInt(process.env.OPENCLI_BROWSER_CONNECT_TIMEOUT ?? '30', 10);
export const DEFAULT_BROWSER_COMMAND_TIMEOUT = parseInt(process.env.OPENCLI_BROWSER_COMMAND_TIMEOUT ?? '60', 10);
@@ -45,7 +42,12 @@ export async function browserSession<T>(
const mcp = new BrowserFactory();
try {
const page = await mcp.connect({ timeout: DEFAULT_BROWSER_CONNECT_TIMEOUT });
return await fn(page);
const result = await fn(page);
// Close the automation window after command completes
if (typeof (page as Page).closeWindow === 'function') {
await (page as Page).closeWindow();
}
return result;
} finally {
await mcp.close().catch(() => {});
}