mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-02 23:41:35 +00:00
* fix(browser): tab creation steals window focus during agent automation Agent-created tabs inherited CDP's foreground default: direct CDP Target.createTarget omitted the background flag, and the extension relay's createTab defaulted to active:true, so every agent tab open activated the new tab (and, on the extension driver, focused the window), interrupting whatever the human was doing in that browser. Direct CDP tab creation now requests background:true (agent tab ownership/selection is target-id based and never depended on activation), and the extension relay defaults an omitted background to true while preserving an explicit background:false, matching the Codex/Claude-in-Chrome model the extension driver mirrors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor(browser): keep focus fix LOC-neutral Preserve background tab creation while keeping the oversized CDP and relay modules within the current LOC ratchet.\n\nCodex-Session: 019f5e93-780a-7350-88f9-1986cdb64914 * fix(browser): honor explicit CDP focus requests Keep background-by-default automation while treating Target.createTarget focus=true as an explicit foreground request in the extension relay. Codex-Session: 019f5e93-780a-7350-88f9-1986cdb64914 * fix(browser): preserve explicit CDP focus semantics Apply the background-by-default automation policy only when focus is omitted, preserving focus=false foreground-tab requests as well as focus=true. Codex-Session: 019f5e93-780a-7350-88f9-1986cdb64914 * fix(browser): preserve create target window focus Carry the resolved CDP focus intent through the extension relay and explicitly focus the containing Chrome window when requested.\n\nCodex-Session: 019f5e93-780a-7350-88f9-1986cdb64914 * style(browser): refresh relay import order * test(secrets): use secure node exec fixtures * test(doctor): secure exec secret fixture * test(doctor): retain narrowed temp path * test(secrets): secure remaining exec fixtures --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Peter Steinberger <steipete@gmail.com>
44 lines
1.5 KiB
TypeScript
44 lines
1.5 KiB
TypeScript
import fs from "node:fs/promises";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
|
|
function shellQuote(value: string): string {
|
|
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
}
|
|
|
|
export async function withSecureTestNodeCommand<T>(
|
|
run: (command: string) => Promise<T>,
|
|
): Promise<T> {
|
|
if (process.platform === "win32") {
|
|
return await run(process.execPath);
|
|
}
|
|
const rootDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-test-node-"));
|
|
const command = path.join(rootDir, "node");
|
|
try {
|
|
await fs.chmod(rootDir, 0o700);
|
|
await fs.writeFile(command, `#!/bin/sh\nexec ${shellQuote(process.execPath)} "$@"\n`, {
|
|
mode: 0o700,
|
|
});
|
|
return await run(command);
|
|
} finally {
|
|
await fs.rm(rootDir, { recursive: true, force: true });
|
|
}
|
|
}
|
|
|
|
export async function withSecureTestNodeExecPath<T>(run: () => Promise<T>): Promise<T> {
|
|
return await withSecureTestNodeCommand(async (command) => {
|
|
const original = Object.getOwnPropertyDescriptor(process, "execPath");
|
|
if (!original) {
|
|
throw new Error("process.execPath descriptor is unavailable");
|
|
}
|
|
// Plugin ${node} materialization reads process.execPath directly. Keep that global swap
|
|
// bounded to one awaited test and always restore it before deleting the wrapper.
|
|
Object.defineProperty(process, "execPath", { ...original, value: command });
|
|
try {
|
|
return await run();
|
|
} finally {
|
|
Object.defineProperty(process, "execPath", original);
|
|
}
|
|
});
|
|
}
|