





















@@ -3,6 +3,11 @@ import path from "node:path";
33import { afterEach, describe, expect, it, vi } from "vitest";
44import { createTrackedTempDirs } from "../test-utils/tracked-temp-dirs.js";
556+const pluginMetadataSnapshotMocks = vi.hoisted(() => ({
7+isPluginMetadataSnapshotCompatible: vi.fn(),
8+loadPluginMetadataSnapshot: vi.fn(),
9+}));
10+611vi.mock("../infra/boundary-file-read.js", async () => {
712const fs = await import("node:fs");
813return {
@@ -107,11 +112,17 @@ vi.mock("../plugins/plugin-metadata-snapshot.js", async () => {
107112],
108113};
109114};
110-return {
111-loadPluginMetadataSnapshot: (params: { workspaceDir?: string }) => ({
115+pluginMetadataSnapshotMocks.isPluginMetadataSnapshotCompatible.mockImplementation(() => false);
116+pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot.mockImplementation(
117+(params: { workspaceDir?: string }) => ({
112118manifestRegistry: loadRegistry(params),
113119normalizePluginId: (id: string) => id.trim(),
114120}),
121+);
122+return {
123+isPluginMetadataSnapshotCompatible:
124+pluginMetadataSnapshotMocks.isPluginMetadataSnapshotCompatible,
125+loadPluginMetadataSnapshot: pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot,
115126};
116127});
117128@@ -161,6 +172,8 @@ const tempDirs = createTrackedTempDirs();
161172162173afterEach(async () => {
163174await tempDirs.cleanup();
175+pluginMetadataSnapshotMocks.isPluginMetadataSnapshotCompatible.mockClear();
176+pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot.mockClear();
164177});
165178166179async function createWorkspaceBundle(params: {
@@ -181,6 +194,87 @@ async function createWorkspaceBundle(params: {
181194}
182195183196describe("loadEnabledBundlePiSettingsSnapshot", () => {
197+it("reuses a compatible plugin metadata snapshot without loading a fresh one", async () => {
198+const workspaceDir = await tempDirs.make("openclaw-workspace-");
199+const pluginRoot = await createWorkspaceBundle({ workspaceDir });
200+const resolvedPluginRoot = await fs.realpath(pluginRoot);
201+await fs.writeFile(
202+path.join(pluginRoot, "settings.json"),
203+JSON.stringify({ hideThinkingBlock: true }),
204+"utf-8",
205+);
206+207+pluginMetadataSnapshotMocks.isPluginMetadataSnapshotCompatible.mockReturnValueOnce(true);
208+pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot.mockClear();
209+210+const snapshot = loadEnabledBundlePiSettingsSnapshot({
211+cwd: workspaceDir,
212+cfg: {
213+plugins: {
214+entries: {
215+"claude-bundle": { enabled: true },
216+},
217+},
218+},
219+pluginMetadataSnapshot: {
220+manifestRegistry: {
221+diagnostics: [],
222+plugins: [
223+{
224+id: "claude-bundle",
225+origin: "workspace",
226+format: "bundle",
227+bundleFormat: "claude",
228+settingsFiles: ["settings.json"],
229+rootDir: resolvedPluginRoot,
230+},
231+],
232+},
233+normalizePluginId: (id: string) => id.trim(),
234+} as unknown as Parameters<
235+typeof loadEnabledBundlePiSettingsSnapshot
236+>[0]["pluginMetadataSnapshot"],
237+});
238+239+expect(snapshot.hideThinkingBlock).toBe(true);
240+expect(pluginMetadataSnapshotMocks.isPluginMetadataSnapshotCompatible).toHaveBeenCalledOnce();
241+expect(pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot).not.toHaveBeenCalled();
242+});
243+244+it("falls back to a fresh plugin metadata load for an incompatible snapshot", async () => {
245+const workspaceDir = await tempDirs.make("openclaw-workspace-");
246+const pluginRoot = await createWorkspaceBundle({ workspaceDir });
247+await fs.writeFile(
248+path.join(pluginRoot, "settings.json"),
249+JSON.stringify({ hideThinkingBlock: true }),
250+"utf-8",
251+);
252+253+pluginMetadataSnapshotMocks.isPluginMetadataSnapshotCompatible.mockReturnValueOnce(false);
254+pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot.mockClear();
255+256+const snapshot = loadEnabledBundlePiSettingsSnapshot({
257+cwd: workspaceDir,
258+cfg: {
259+plugins: {
260+entries: {
261+"claude-bundle": { enabled: true },
262+},
263+},
264+},
265+pluginMetadataSnapshot: {
266+manifestRegistry: { diagnostics: [], plugins: [] },
267+normalizePluginId: (id: string) => id.trim(),
268+} as unknown as Parameters<
269+typeof loadEnabledBundlePiSettingsSnapshot
270+>[0]["pluginMetadataSnapshot"],
271+});
272+273+expect(snapshot.hideThinkingBlock).toBe(true);
274+expect(pluginMetadataSnapshotMocks.isPluginMetadataSnapshotCompatible).toHaveBeenCalledOnce();
275+expect(pluginMetadataSnapshotMocks.loadPluginMetadataSnapshot).toHaveBeenCalledOnce();
276+});
277+184278it("loads sanitized settings and MCP defaults from enabled bundle plugins", async () => {
185279const workspaceDir = await tempDirs.make("openclaw-workspace-");
186280const pluginRoot = await createWorkspaceBundle({ workspaceDir });
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。