fix(plugins): prevent schema load from re-activating plugin registry (#54971)

Merged via squash.

Prepared head SHA: dd1ed1d519
Co-authored-by: Aftabbs <112916888+Aftabbs@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
This commit is contained in:
Aftab
2026-04-09 14:47:26 +05:30
committed by GitHub
parent fbbb4f02d1
commit fa2fab7060

View File

@@ -1,4 +1,12 @@
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { createEmptyPluginRegistry } from "../plugins/registry-empty.js";
import {
getActivePluginRegistry,
getActivePluginRegistryKey,
getActivePluginRegistryVersion,
resetPluginRuntimeStateForTest,
setActivePluginRegistry,
} from "../plugins/runtime.js";
import type { ConfigFileSnapshot, OpenClawConfig } from "./types.js";
const mockLoadConfig = vi.hoisted(() => vi.fn<() => OpenClawConfig>());
@@ -144,6 +152,10 @@ beforeAll(async () => {
await import("./runtime-schema.js"));
});
afterEach(() => {
resetPluginRuntimeStateForTest();
});
describe("readBestEffortRuntimeConfigSchema", () => {
beforeEach(() => {
vi.clearAllMocks();
@@ -211,4 +223,27 @@ describe("loadGatewayRuntimeConfigSchema", () => {
expect(channelProps?.telegram).toBeTruthy();
expect(channelProps?.matrix).toBeTruthy();
});
it("does not activate or replace the active plugin registry across repeated schema loads (regression guard for #54816)", () => {
// Each MCP connection triggers a config.schema / config.get gateway request which calls
// loadGatewayRuntimeConfigSchema. The original bug caused a fresh full plugin registry to
// be activated on every call, re-running registerFull for all channel plugins including
// Feishu. Verify that repeated calls keep using manifest metadata without replacing the
// already-active runtime registry or mutating its activation version.
const activeRegistry = createEmptyPluginRegistry();
setActivePluginRegistry(activeRegistry, "startup-registry");
const versionBefore = getActivePluginRegistryVersion();
loadGatewayRuntimeConfigSchema();
loadGatewayRuntimeConfigSchema();
loadGatewayRuntimeConfigSchema();
expect(mockLoadPluginManifestRegistry).toHaveBeenCalledTimes(3);
for (const call of mockLoadPluginManifestRegistry.mock.calls) {
expect(call[0]).toMatchObject({ cache: false });
}
expect(getActivePluginRegistry()).toBe(activeRegistry);
expect(getActivePluginRegistryKey()).toBe("startup-registry");
expect(getActivePluginRegistryVersion()).toBe(versionBefore);
});
});