
























@@ -5,14 +5,63 @@ import { buildPluginsCommandParams } from "./commands.test-harness.js";
5566const readConfigFileSnapshotMock = vi.hoisted(() => vi.fn());
77const validateConfigObjectWithPluginsMock = vi.hoisted(() => vi.fn());
8-const replaceConfigFileMock = vi.hoisted(() => vi.fn(async () => undefined));
8+const replaceConfigFileMock = vi.hoisted(() => vi.fn(async (_params: unknown) => undefined));
99const buildPluginRegistrySnapshotReportMock = vi.hoisted(() => vi.fn());
1010const buildPluginDiagnosticsReportMock = vi.hoisted(() => vi.fn());
1111const buildPluginInspectReportMock = vi.hoisted(() => vi.fn());
1212const buildAllPluginInspectReportsMock = vi.hoisted(() => vi.fn());
1313const formatPluginCompatibilityNoticeMock = vi.hoisted(() => vi.fn(() => "ok"));
1414const refreshPluginRegistryAfterConfigMutationMock = vi.hoisted(() => vi.fn(async () => undefined));
151516+type ConfigSnapshotMock = {
17+path?: string;
18+hash?: string | null;
19+parsed?: OpenClawConfig | null;
20+sourceConfig?: OpenClawConfig;
21+resolved?: OpenClawConfig;
22+runtimeConfig?: OpenClawConfig;
23+};
24+25+type TransformConfigFileWithRetryMockParams<T = unknown> = {
26+afterWrite?: unknown;
27+transform: (
28+currentConfig: OpenClawConfig,
29+context: { snapshot: ConfigSnapshotMock; previousHash: string | null; attempt: number },
30+) =>
31+| Promise<{ nextConfig: OpenClawConfig; result?: T }>
32+| { nextConfig: OpenClawConfig; result?: T };
33+};
34+35+function configFromSnapshot(snapshot: ConfigSnapshotMock): OpenClawConfig {
36+return structuredClone(
37+snapshot.sourceConfig ?? snapshot.resolved ?? snapshot.runtimeConfig ?? snapshot.parsed ?? {},
38+);
39+}
40+41+async function transformConfigFileWithRetryMock<T = unknown>(
42+params: TransformConfigFileWithRetryMockParams<T>,
43+) {
44+const snapshot = (await readConfigFileSnapshotMock()) as ConfigSnapshotMock;
45+const previousHash = snapshot.hash ?? null;
46+const transformed = await params.transform(configFromSnapshot(snapshot), {
47+ snapshot,
48+ previousHash,
49+attempt: 0,
50+});
51+const afterWrite = params.afterWrite ?? { mode: "auto" };
52+await replaceConfigFileMock({ nextConfig: transformed.nextConfig, afterWrite });
53+return {
54+path: snapshot.path ?? "/tmp/openclaw.json",
55+ previousHash,
56+ snapshot,
57+nextConfig: transformed.nextConfig,
58+result: transformed.result,
59+attempts: 1,
60+ afterWrite,
61+followUp: { action: "none" },
62+};
63+}
64+1665vi.mock("../../cli/npm-resolution.js", () => ({
1766buildNpmInstallRecordFields: vi.fn(),
1867}));
@@ -34,6 +83,7 @@ vi.mock("../../config/config.js", () => ({
3483readConfigFileSnapshot: readConfigFileSnapshotMock,
3584validateConfigObjectWithPlugins: validateConfigObjectWithPluginsMock,
3685replaceConfigFile: replaceConfigFileMock,
86+transformConfigFileWithRetry: transformConfigFileWithRetryMock,
3787}));
38883989vi.mock("../../infra/archive.js", () => ({
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。