Compare commits

...

2 Commits

Author SHA1 Message Date
Peter Steinberger
050e6467fc fix: add changelog for Chrome restore prompt (#1419) (thanks @jamesgroat) 2026-01-22 05:16:38 +00:00
James Groat
398cb5433d Browser: suppress Chrome restore prompt 2026-01-22 04:56:26 +00:00
4 changed files with 40 additions and 2 deletions

View File

@ -22,6 +22,7 @@ Docs: https://docs.clawd.bot
- Doctor: avoid recreating WhatsApp config when only legacy routing keys remain. (#900)
- Doctor: warn when gateway.mode is unset with configure/config guidance.
- OpenCode Zen: route models to the Zen API shape per family so proxy endpoints are used. (#1416)
- Browser: suppress Chrome restore prompts for managed profiles. (#1419) Thanks @jamesgroat.
- macOS: include Textual syntax highlighting resources in packaged app to prevent chat crashes. (#1362)
- Cron: cap reminder context history to 10 messages and honor `contextMessages`. (#1103) Thanks @mkbehr.
- Exec approvals: treat main as the default agent + migrate legacy default allowlists. (#1417) Thanks @czekaj.

View File

@ -180,3 +180,11 @@ export function decorateClawdProfile(
// ignore
}
}
export function ensureProfileCleanExit(userDataDir: string) {
const preferencesPath = path.join(userDataDir, "Default", "Preferences");
const prefs = safeReadJson(preferencesPath) ?? {};
setDeep(prefs, ["exit_type"], "Normal");
setDeep(prefs, ["exited_cleanly"], true);
safeWriteJson(preferencesPath, prefs);
}

View File

@ -7,6 +7,7 @@ import { afterEach, describe, expect, it, vi } from "vitest";
import {
decorateClawdProfile,
ensureProfileCleanExit,
findChromeExecutableMac,
findChromeExecutableWindows,
isChromeReachable,
@ -103,6 +104,18 @@ describe("browser chrome profile decoration", () => {
}
});
it("writes clean exit prefs to avoid restore prompts", async () => {
const userDataDir = await fsp.mkdtemp(path.join(os.tmpdir(), "clawdbot-chrome-test-"));
try {
ensureProfileCleanExit(userDataDir);
const prefs = await readJson(path.join(userDataDir, "Default", "Preferences"));
expect(prefs.exit_type).toBe("Normal");
expect(prefs.exited_cleanly).toBe(true);
} finally {
await fsp.rm(userDataDir, { recursive: true, force: true });
}
});
it("is idempotent when rerun on an existing profile", async () => {
const userDataDir = await fsp.mkdtemp(path.join(os.tmpdir(), "clawdbot-chrome-test-"));
try {

View File

@ -13,7 +13,11 @@ import {
type BrowserExecutable,
resolveBrowserExecutableForPlatform,
} from "./chrome.executables.js";
import { decorateClawdProfile, isProfileDecorated } from "./chrome.profile-decoration.js";
import {
decorateClawdProfile,
ensureProfileCleanExit,
isProfileDecorated,
} from "./chrome.profile-decoration.js";
import type { ResolvedBrowserConfig, ResolvedBrowserProfile } from "./config.js";
import { DEFAULT_CLAWD_BROWSER_COLOR, DEFAULT_CLAWD_BROWSER_PROFILE_NAME } from "./constants.js";
@ -26,7 +30,11 @@ export {
findChromeExecutableWindows,
resolveBrowserExecutableForPlatform,
} from "./chrome.executables.js";
export { decorateClawdProfile, isProfileDecorated } from "./chrome.profile-decoration.js";
export {
decorateClawdProfile,
ensureProfileCleanExit,
isProfileDecorated,
} from "./chrome.profile-decoration.js";
function exists(filePath: string) {
try {
@ -178,6 +186,8 @@ export async function launchClawdChrome(
"--disable-background-networking",
"--disable-component-update",
"--disable-features=Translate,MediaRouter",
"--disable-session-crashed-bubble",
"--hide-crash-restore-bubble",
"--password-store=basic",
];
@ -246,6 +256,12 @@ export async function launchClawdChrome(
}
}
try {
ensureProfileCleanExit(userDataDir);
} catch (err) {
log.warn(`clawd browser clean-exit prefs failed: ${String(err)}`);
}
const proc = spawnOnce();
// Wait for CDP to come up.
const readyDeadline = Date.now() + 15_000;