Files
openclaw/src/browser/resolved-config-refresh.ts
2026-03-09 00:25:43 +00:00

95 lines
2.8 KiB
TypeScript

import { createConfigIO, loadConfig } from "../config/config.js";
import { resolveBrowserConfig, resolveProfile, type ResolvedBrowserProfile } from "./config.js";
import type { BrowserServerState } from "./server-context.types.js";
function changedProfileInvariants(
current: ResolvedBrowserProfile,
next: ResolvedBrowserProfile,
): string[] {
const changed: string[] = [];
if (current.cdpUrl !== next.cdpUrl) {
changed.push("cdpUrl");
}
if (current.cdpPort !== next.cdpPort) {
changed.push("cdpPort");
}
if (current.driver !== next.driver) {
changed.push("driver");
}
if (current.attachOnly !== next.attachOnly) {
changed.push("attachOnly");
}
if (current.cdpIsLoopback !== next.cdpIsLoopback) {
changed.push("cdpIsLoopback");
}
return changed;
}
function applyResolvedConfig(
current: BrowserServerState,
freshResolved: BrowserServerState["resolved"],
) {
current.resolved = freshResolved;
for (const [name, runtime] of current.profiles) {
const nextProfile = resolveProfile(freshResolved, name);
if (nextProfile) {
const changed = changedProfileInvariants(runtime.profile, nextProfile);
if (changed.length > 0) {
runtime.reconcile = {
previousProfile: runtime.profile,
reason: `profile invariants changed: ${changed.join(", ")}`,
};
runtime.lastTargetId = null;
}
runtime.profile = nextProfile;
continue;
}
runtime.reconcile = {
previousProfile: runtime.profile,
reason: "profile removed from config",
};
runtime.lastTargetId = null;
if (!runtime.running) {
current.profiles.delete(name);
}
}
}
export function refreshResolvedBrowserConfigFromDisk(params: {
current: BrowserServerState;
refreshConfigFromDisk: boolean;
mode: "cached" | "fresh";
}) {
if (!params.refreshConfigFromDisk) {
return;
}
const cfg = params.mode === "fresh" ? createConfigIO().loadConfig() : loadConfig();
const freshResolved = resolveBrowserConfig(cfg.browser, cfg);
applyResolvedConfig(params.current, freshResolved);
}
export function resolveBrowserProfileWithHotReload(params: {
current: BrowserServerState;
refreshConfigFromDisk: boolean;
name: string;
}): ResolvedBrowserProfile | null {
refreshResolvedBrowserConfigFromDisk({
current: params.current,
refreshConfigFromDisk: params.refreshConfigFromDisk,
mode: "cached",
});
let profile = resolveProfile(params.current.resolved, params.name);
if (profile) {
return profile;
}
// Hot-reload: profile missing; retry with a fresh disk read without flushing the global cache.
refreshResolvedBrowserConfigFromDisk({
current: params.current,
refreshConfigFromDisk: params.refreshConfigFromDisk,
mode: "fresh",
});
profile = resolveProfile(params.current.resolved, params.name);
return profile;
}