Spracherkennung für: .ts vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]
import type { OpenClawConfig } from "./types.js";
export type RuntimeConfigSnapshotRefreshParams = {
sourceConfig: OpenClawConfig;
};
export type RuntimeConfigSnapshotRefreshHandler = {
refresh: (params: RuntimeConfigSnapshotRefreshParams) => boolean | Promise<boolean>;
clearOnRefreshFailure?: () => void;
};
export type RuntimeConfigWriteNotification = {
configPath: string;
sourceConfig: OpenClawConfig;
runtimeConfig: OpenClawConfig;
persistedHash: string;
writtenAtMs: number;
};
let runtimeConfigSnapshot: OpenClawConfig | null = null;
let runtimeConfigSourceSnapshot: OpenClawConfig | null = null;
let runtimeConfigSnapshotRefreshHandler: RuntimeConfigSnapshotRefreshHandler | null = null;
const runtimeConfigWriteListeners = new Set<(event: RuntimeConfigWriteNotification) => void>();
function stableConfigStringify(value: unknown): string {
if (value === null || typeof value !== "object") {
return JSON.stringify(value) ?? "null";
}
if (Array.isArray(value)) {
return `[${value.map((entry) => stableConfigStringify(entry)).join(",")}]`;
}
const record = value as Record<string, unknown>;
const keys = Object.keys(record).toSorted();
return `{${keys
.map((key) => `${JSON.stringify(key)}:${stableConfigStringify(record[key])}`)
.join(",")}}`;
}
function configSnapshotsMatch(left: OpenClawConfig, right: OpenClawConfig): boolean {
if (left === right) {
return true;
}
try {
return stableConfigStringify(left) === stableConfigStringify(right);
} catch {
return false;
}
}
export function setRuntimeConfigSnapshot(
config: OpenClawConfig,
sourceConfig?: OpenClawConfig,
): void {
runtimeConfigSnapshot = config;
runtimeConfigSourceSnapshot = sourceConfig ?? null;
}
export function resetConfigRuntimeState(): void {
runtimeConfigSnapshot = null;
runtimeConfigSourceSnapshot = null;
}
export function clearRuntimeConfigSnapshot(): void {
resetConfigRuntimeState();
}
export function getRuntimeConfigSnapshot(): OpenClawConfig | null {
return runtimeConfigSnapshot;
}
export function getRuntimeConfigSourceSnapshot(): OpenClawConfig | null {
return runtimeConfigSourceSnapshot;
}
export function selectApplicableRuntimeConfig(params: {
inputConfig?: OpenClawConfig;
runtimeConfig?: OpenClawConfig | null;
runtimeSourceConfig?: OpenClawConfig | null;
}): OpenClawConfig | undefined {
const runtimeConfig = params.runtimeConfig ?? null;
if (!runtimeConfig) {
return params.inputConfig;
}
const inputConfig = params.inputConfig;
if (!inputConfig) {
return runtimeConfig;
}
if (inputConfig === runtimeConfig) {
return inputConfig;
}
const runtimeSourceConfig = params.runtimeSourceConfig ?? null;
if (!runtimeSourceConfig) {
return runtimeConfig;
}
if (configSnapshotsMatch(inputConfig, runtimeSourceConfig)) {
return runtimeConfig;
}
return inputConfig;
}
export function setRuntimeConfigSnapshotRefreshHandler(
refreshHandler: RuntimeConfigSnapshotRefreshHandler | null,
): void {
runtimeConfigSnapshotRefreshHandler = refreshHandler;
}
export function getRuntimeConfigSnapshotRefreshHandler(): RuntimeConfigSnapshotRefreshHandler | null {
return runtimeConfigSnapshotRefreshHandler;
}
export function registerRuntimeConfigWriteListener(
listener: (event: RuntimeConfigWriteNotification) => void,
): () => void {
runtimeConfigWriteListeners.add(listener);
return () => {
runtimeConfigWriteListeners.delete(listener);
};
}
export function notifyRuntimeConfigWriteListeners(event: RuntimeConfigWriteNotification): void {
for (const listener of runtimeConfigWriteListeners) {
try {
listener(event);
} catch {
// Best-effort observer path only; successful writes must still complete.
}
}
}
export function loadPinnedRuntimeConfig(loadFresh: () => OpenClawConfig): OpenClawConfig {
if (runtimeConfigSnapshot) {
return runtimeConfigSnapshot;
}
const config = loadFresh();
setRuntimeConfigSnapshot(config);
return getRuntimeConfigSnapshot() ?? config;
}
export async function finalizeRuntimeSnapshotWrite(params: {
nextSourceConfig: OpenClawConfig;
hadRuntimeSnapshot: boolean;
hadBothSnapshots: boolean;
loadFreshConfig: () => OpenClawConfig;
notifyCommittedWrite: () => void;
createRefreshError: (detail: string, cause: unknown) => Error;
formatRefreshError: (error: unknown) => string;
}): Promise<void> {
const refreshHandler = getRuntimeConfigSnapshotRefreshHandler();
if (refreshHandler) {
try {
const refreshed = await refreshHandler.refresh({ sourceConfig: params.nextSourceConfig });
if (refreshed) {
params.notifyCommittedWrite();
return;
}
} catch (error) {
try {
refreshHandler.clearOnRefreshFailure?.();
} catch {
// Keep the original refresh failure as the surfaced error.
}
throw params.createRefreshError(params.formatRefreshError(error), error);
}
}
if (params.hadBothSnapshots) {
const fresh = params.loadFreshConfig();
setRuntimeConfigSnapshot(fresh, params.nextSourceConfig);
params.notifyCommittedWrite();
return;
}
if (params.hadRuntimeSnapshot) {
const fresh = params.loadFreshConfig();
setRuntimeConfigSnapshot(fresh);
params.notifyCommittedWrite();
return;
}
setRuntimeConfigSnapshot(params.loadFreshConfig());
params.notifyCommittedWrite();
}
¤ Dauer der Verarbeitung: 0.24 Sekunden
(vorverarbeitet am 2026-04-27)
¤
*© Formatika GbR, Deutschland