perf(test): trim bundled facade hot paths

This commit is contained in:
Peter Steinberger
2026-04-07 00:59:18 +01:00
parent fbebf6147c
commit 8c38c662c1
4 changed files with 263 additions and 194 deletions

View File

@@ -2,22 +2,21 @@ import fs from "node:fs";
import path from "node:path";
import { afterEach, describe, expect, it, vi } from "vitest";
import { clearRuntimeConfigSnapshot, setRuntimeConfigSnapshot } from "../config/config.js";
import { createPluginActivationSource, normalizePluginsConfig } from "../plugins/config-state.js";
import { clearPluginDiscoveryCache } from "../plugins/discovery.js";
import { clearPluginManifestRegistryCache } from "../plugins/manifest-registry.js";
import {
__testing,
canLoadActivatedBundledPluginPublicSurface,
listImportedBundledPluginFacadeIds,
loadActivatedBundledPluginPublicSurfaceModuleSync,
loadBundledPluginPublicSurfaceModuleSync,
resetFacadeRuntimeStateForTest,
tryLoadActivatedBundledPluginPublicSurfaceModuleSync,
} from "./facade-runtime.js";
import { createPluginSdkTestHarness } from "./test-helpers.js";
const { createTempDirSync } = createPluginSdkTestHarness();
const originalBundledPluginsDir = process.env.OPENCLAW_BUNDLED_PLUGINS_DIR;
const originalStateDir = process.env.OPENCLAW_STATE_DIR;
const FACADE_RUNTIME_GLOBAL = "__openclawTestLoadBundledPluginPublicSurfaceModuleSync";
function createBundledPluginDir(prefix: string, marker: string): string {
const rootDir = createTempDirSync(prefix);
@@ -41,36 +40,6 @@ function createThrowingPluginDir(prefix: string): string {
return rootDir;
}
function createCircularPluginDir(prefix: string): string {
const rootDir = createTempDirSync(prefix);
fs.mkdirSync(path.join(rootDir, "demo"), { recursive: true });
fs.writeFileSync(
path.join(rootDir, "facade.mjs"),
[
`const loadBundledPluginPublicSurfaceModuleSync = globalThis.${FACADE_RUNTIME_GLOBAL};`,
`if (typeof loadBundledPluginPublicSurfaceModuleSync !== "function") {`,
' throw new Error("missing facade runtime test loader");',
"}",
`export const marker = loadBundledPluginPublicSurfaceModuleSync({ dirName: "demo", artifactBasename: "api.js" }).marker;`,
"",
].join("\n"),
"utf8",
);
fs.writeFileSync(
path.join(rootDir, "demo", "helper.js"),
['import { marker } from "../facade.mjs";', "export const circularMarker = marker;", ""].join(
"\n",
),
"utf8",
);
fs.writeFileSync(
path.join(rootDir, "demo", "api.js"),
['import "./helper.js";', 'export const marker = "circular-ok";', ""].join("\n"),
"utf8",
);
return rootDir;
}
afterEach(() => {
vi.restoreAllMocks();
clearRuntimeConfigSnapshot();
@@ -78,7 +47,6 @@ afterEach(() => {
clearPluginDiscoveryCache();
clearPluginManifestRegistryCache();
vi.doUnmock("../plugins/manifest-registry.js");
delete (globalThis as typeof globalThis & Record<string, unknown>)[FACADE_RUNTIME_GLOBAL];
if (originalBundledPluginsDir === undefined) {
delete process.env.OPENCLAW_BUNDLED_PLUGINS_DIR;
} else {
@@ -97,106 +65,107 @@ describe("plugin-sdk facade runtime", () => {
const overrideB = createBundledPluginDir("openclaw-facade-runtime-b-", "override-b");
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = overrideA;
const fromA = loadBundledPluginPublicSurfaceModuleSync<{ marker: string }>({
const fromA = __testing.resolveFacadeModuleLocation({
dirName: "demo",
artifactBasename: "api.js",
});
expect(fromA.marker).toBe("override-a");
expect(fromA).toEqual({
modulePath: path.join(overrideA, "demo", "api.js"),
boundaryRoot: overrideA,
});
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = overrideB;
const fromB = loadBundledPluginPublicSurfaceModuleSync<{ marker: string }>({
const fromB = __testing.resolveFacadeModuleLocation({
dirName: "demo",
artifactBasename: "api.js",
});
expect(fromB.marker).toBe("override-b");
expect(fromB).toEqual({
modulePath: path.join(overrideB, "demo", "api.js"),
boundaryRoot: overrideB,
});
});
it("returns the same object identity on repeated calls (sentinel consistency)", () => {
const dir = createBundledPluginDir("openclaw-facade-identity-", "identity-check");
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = dir;
const location = {
modulePath: path.join(dir, "demo", "api.js"),
boundaryRoot: dir,
};
const loader = vi.fn(() => ({ marker: "identity-check" }));
const first = loadBundledPluginPublicSurfaceModuleSync<{ marker: string }>({
dirName: "demo",
artifactBasename: "api.js",
const first = __testing.loadFacadeModuleAtLocationSync<{ marker: string }>({
location,
trackedPluginId: "demo",
loadModule: loader,
});
const second = loadBundledPluginPublicSurfaceModuleSync<{ marker: string }>({
dirName: "demo",
artifactBasename: "api.js",
const second = __testing.loadFacadeModuleAtLocationSync<{ marker: string }>({
location,
trackedPluginId: "demo",
loadModule: loader,
});
expect(first).toBe(second);
expect(first.marker).toBe("identity-check");
expect(listImportedBundledPluginFacadeIds()).toEqual(["demo"]);
expect(loader).toHaveBeenCalledTimes(1);
});
it("breaks circular facade re-entry during module evaluation", () => {
const dir = createCircularPluginDir("openclaw-facade-circular-");
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = dir;
(globalThis as typeof globalThis & Record<string, unknown>)[FACADE_RUNTIME_GLOBAL] =
loadBundledPluginPublicSurfaceModuleSync;
const dir = createBundledPluginDir("openclaw-facade-circular-", "circular-ok");
const location = {
modulePath: path.join(dir, "demo", "api.js"),
boundaryRoot: dir,
};
let reentered: { marker?: string } | undefined;
const loader = vi.fn(() => {
reentered = __testing.loadFacadeModuleAtLocationSync<{ marker?: string }>({
location,
trackedPluginId: "demo",
loadModule: loader,
});
return { marker: "circular-ok" };
});
const loaded = loadBundledPluginPublicSurfaceModuleSync<{ marker: string }>({
dirName: "demo",
artifactBasename: "api.js",
const loaded = __testing.loadFacadeModuleAtLocationSync<{ marker: string }>({
location,
trackedPluginId: "demo",
loadModule: loader,
});
expect(loaded.marker).toBe("circular-ok");
expect(reentered).toBe(loaded);
expect(reentered?.marker).toBe("circular-ok");
expect(loader).toHaveBeenCalledTimes(1);
});
it("back-fills the sentinel before post-load facade tracking re-enters", async () => {
it("back-fills the sentinel before post-load facade tracking re-enters", () => {
const dir = createBundledPluginDir("openclaw-facade-post-load-", "post-load-ok");
const location = {
modulePath: path.join(dir, "demo", "api.js"),
boundaryRoot: dir,
};
const reentryMarkers: Array<string | undefined> = [];
const loader = vi.fn(() => ({ marker: "post-load-ok" }));
vi.resetModules();
vi.doMock("../plugins/manifest-registry.js", async (importOriginal) => {
const actual = await importOriginal<typeof import("../plugins/manifest-registry.js")>();
return {
...actual,
loadPluginManifestRegistry: vi.fn(() => {
const load = (
globalThis as typeof globalThis & {
[FACADE_RUNTIME_GLOBAL]?: typeof loadBundledPluginPublicSurfaceModuleSync;
}
)[FACADE_RUNTIME_GLOBAL];
if (typeof load !== "function") {
throw new Error("missing facade runtime test loader");
}
const reentered = load<{ marker?: string }>({
dirName: "demo",
artifactBasename: "api.js",
});
reentryMarkers.push(reentered.marker);
return {
plugins: [
{
id: "demo",
rootDir: path.join(dir, "demo"),
origin: "bundled",
channels: ["demo"],
},
],
diagnostics: [],
};
}),
};
});
const facadeRuntime = await import("./facade-runtime.js");
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = dir;
(globalThis as typeof globalThis & Record<string, unknown>)[FACADE_RUNTIME_GLOBAL] =
facadeRuntime.loadBundledPluginPublicSurfaceModuleSync;
const loaded = facadeRuntime.loadBundledPluginPublicSurfaceModuleSync<{ marker: string }>({
dirName: "demo",
artifactBasename: "api.js",
const loaded = __testing.loadFacadeModuleAtLocationSync<{ marker: string }>({
location,
trackedPluginId: () => {
const reentered = __testing.loadFacadeModuleAtLocationSync<{ marker?: string }>({
location,
trackedPluginId: "demo",
loadModule: loader,
});
reentryMarkers.push(reentered.marker);
return "demo";
},
loadModule: loader,
});
expect(loaded.marker).toBe("post-load-ok");
expect(reentryMarkers.length).toBeGreaterThan(0);
expect(reentryMarkers.every((marker) => marker === "post-load-ok")).toBe(true);
expect(facadeRuntime.listImportedBundledPluginFacadeIds()).toEqual(["demo"]);
facadeRuntime.resetFacadeRuntimeStateForTest();
vi.doUnmock("../plugins/manifest-registry.js");
vi.resetModules();
expect(listImportedBundledPluginFacadeIds()).toEqual(["demo"]);
expect(loader).toHaveBeenCalledTimes(1);
});
it("clears the cache on load failure so retries re-execute", () => {
const dir = createThrowingPluginDir("openclaw-facade-throw-");
@@ -221,30 +190,48 @@ describe("plugin-sdk facade runtime", () => {
});
it("blocks runtime-api facade loads for bundled plugins that are not activated", () => {
setRuntimeConfigSnapshot({});
const access = __testing.evaluateBundledPluginPublicSurfaceAccess({
params: {
dirName: "discord",
artifactBasename: "runtime-api.js",
},
manifestRecord: {
id: "discord",
origin: "bundled",
enabledByDefault: false,
rootDir: "/tmp/discord",
channels: ["discord"],
},
config: {},
normalizedPluginsConfig: normalizePluginsConfig(),
activationSource: createPluginActivationSource({ config: {} }),
autoEnabledReasons: {},
});
expect(
canLoadActivatedBundledPluginPublicSurface({
dirName: "discord",
artifactBasename: "runtime-api.js",
}),
).toBe(false);
expect(access.allowed).toBe(false);
expect(access.pluginId).toBe("discord");
expect(access.reason).toBeTruthy();
expect(() =>
loadActivatedBundledPluginPublicSurfaceModuleSync({
dirName: "discord",
artifactBasename: "runtime-api.js",
__testing.throwForBundledPluginPublicSurfaceAccess({
access,
request: {
dirName: "discord",
artifactBasename: "runtime-api.js",
},
}),
).toThrow(/Bundled plugin public surface access blocked/);
expect(
tryLoadActivatedBundledPluginPublicSurfaceModuleSync({
dirName: "discord",
artifactBasename: "runtime-api.js",
}),
).toBeNull();
expect(access.allowed).toBe(false);
});
it("allows runtime-api facade loads when the bundled plugin is explicitly enabled", () => {
setRuntimeConfigSnapshot({
const dir = createTempDirSync("openclaw-facade-runtime-enabled-");
fs.mkdirSync(path.join(dir, "discord"), { recursive: true });
fs.writeFileSync(
path.join(dir, "discord", "runtime-api.js"),
'export const marker = "runtime-api-enabled";\n',
"utf8",
);
const config = {
plugins: {
entries: {
discord: {
@@ -252,14 +239,38 @@ describe("plugin-sdk facade runtime", () => {
},
},
},
});
expect(
canLoadActivatedBundledPluginPublicSurface({
} as const;
const access = __testing.evaluateBundledPluginPublicSurfaceAccess({
params: {
dirName: "discord",
artifactBasename: "runtime-api.js",
}),
).toBe(true);
},
manifestRecord: {
id: "discord",
origin: "bundled",
enabledByDefault: false,
rootDir: "/tmp/discord",
channels: ["discord"],
},
config,
normalizedPluginsConfig: normalizePluginsConfig(config.plugins),
activationSource: createPluginActivationSource({ config }),
autoEnabledReasons: {},
});
const loader = vi.fn(() => ({ marker: "runtime-api-enabled" }));
const location = {
modulePath: path.join(dir, "discord", "runtime-api.js"),
boundaryRoot: dir,
};
expect(access.allowed).toBe(true);
const loaded = __testing.loadFacadeModuleAtLocationSync<{ marker: string }>({
location,
trackedPluginId: "discord",
loadModule: loader,
});
expect(loaded.marker).toBe("runtime-api-enabled");
expect(loader).toHaveBeenCalledTimes(1);
});
it("resolves a globally-installed plugin whose rootDir basename matches the dirName", () => {

View File

@@ -463,33 +463,59 @@ function resolveBundledPluginPublicSurfaceAccess(params: {
}
const { config, normalizedPluginsConfig, activationSource, autoEnabledReasons } =
getFacadeBoundaryResolvedConfig();
const activationState = resolveEffectivePluginActivationState({
id: manifestRecord.id,
origin: manifestRecord.origin,
config: normalizedPluginsConfig,
rootConfig: config,
enabledByDefault: manifestRecord.enabledByDefault,
const resolved = evaluateBundledPluginPublicSurfaceAccess({
params,
manifestRecord,
config,
normalizedPluginsConfig,
activationSource,
autoEnabledReason: autoEnabledReasons[manifestRecord.id]?.[0],
autoEnabledReasons,
});
if (activationState.enabled) {
const resolved = {
allowed: true,
pluginId: manifestRecord.id,
};
cachedFacadePublicSurfaceAccessByKey.set(key, resolved);
return resolved;
}
const resolved = {
allowed: false,
pluginId: manifestRecord.id,
reason: activationState.reason ?? "plugin runtime is not activated",
};
cachedFacadePublicSurfaceAccessByKey.set(key, resolved);
return resolved;
}
function evaluateBundledPluginPublicSurfaceAccess(params: {
params: BundledPluginPublicSurfaceParams;
manifestRecord: FacadePluginManifestLike;
config: OpenClawConfig;
normalizedPluginsConfig: ReturnType<typeof normalizePluginsConfig>;
activationSource: ReturnType<typeof createPluginActivationSource>;
autoEnabledReasons: Record<string, string[]>;
}): { allowed: boolean; pluginId?: string; reason?: string } {
const activationState = resolveEffectivePluginActivationState({
id: params.manifestRecord.id,
origin: params.manifestRecord.origin,
config: params.normalizedPluginsConfig,
rootConfig: params.config,
enabledByDefault: params.manifestRecord.enabledByDefault,
activationSource: params.activationSource,
autoEnabledReason: params.autoEnabledReasons[params.manifestRecord.id]?.[0],
});
if (activationState.enabled) {
return {
allowed: true,
pluginId: params.manifestRecord.id,
};
}
return {
allowed: false,
pluginId: params.manifestRecord.id,
reason: activationState.reason ?? "plugin runtime is not activated",
};
}
function throwForBundledPluginPublicSurfaceAccess(params: {
access: { allowed: boolean; pluginId?: string; reason?: string };
request: BundledPluginPublicSurfaceParams;
}): never {
const pluginLabel = params.access.pluginId ?? params.request.dirName;
throw new Error(
`Bundled plugin public surface access blocked for "${pluginLabel}" via ${params.request.dirName}/${params.request.artifactBasename}: ${params.access.reason ?? "plugin runtime is not activated"}`,
);
}
function createLazyFacadeValueLoader<T>(load: () => T): () => T {
let loaded = false;
let value: T;
@@ -552,16 +578,22 @@ export function createLazyFacadeArrayValue<T extends readonly unknown[]>(load: (
return createLazyFacadeProxyValue({ load, target: [] });
}
export function loadBundledPluginPublicSurfaceModuleSync<T extends object>(params: {
type FacadeModuleLocation = {
modulePath: string;
boundaryRoot: string;
};
type BundledPluginPublicSurfaceParams = {
dirName: string;
artifactBasename: string;
};
function loadFacadeModuleAtLocationSync<T extends object>(params: {
location: FacadeModuleLocation;
trackedPluginId: string | (() => string);
loadModule?: (modulePath: string) => T;
}): T {
const location = resolveFacadeModuleLocation(params);
if (!location) {
throw new Error(
`Unable to resolve bundled plugin public surface ${params.dirName}/${params.artifactBasename}`,
);
}
const { location } = params;
const cached = loadedFacadeModules.get(location.modulePath);
if (cached) {
return cached as T;
@@ -582,10 +614,9 @@ export function loadBundledPluginPublicSurfaceModuleSync<T extends object>(param
rejectHardlinks: false,
});
if (!opened.ok) {
throw new Error(
`Unable to open bundled plugin public surface ${params.dirName}/${params.artifactBasename}`,
{ cause: opened.error },
);
throw new Error(`Unable to open bundled plugin public surface ${location.modulePath}`, {
cause: opened.error,
});
}
fs.closeSync(opened.fd);
@@ -600,14 +631,20 @@ export function loadBundledPluginPublicSurfaceModuleSync<T extends object>(param
let loaded: T;
try {
loaded = getJiti(location.modulePath)(location.modulePath) as T;
loaded =
params.loadModule?.(location.modulePath) ??
(getJiti(location.modulePath)(location.modulePath) as T);
// Back-fill the sentinel before resolving plugin ownership. That lookup can
// trigger config loading, plugin auto-enable, and other facade reads that
// re-enter this loader for the same module path.
Object.assign(sentinel, loaded);
// Track the owning plugin after the module exports are visible through the
// sentinel, so re-entrant callers never observe an empty facade object.
loadedFacadePluginIds.add(resolveTrackedFacadePluginId(params));
loadedFacadePluginIds.add(
typeof params.trackedPluginId === "function"
? params.trackedPluginId()
: params.trackedPluginId,
);
} catch (err) {
loadedFacadeModules.delete(location.modulePath);
throw err;
@@ -616,6 +653,34 @@ export function loadBundledPluginPublicSurfaceModuleSync<T extends object>(param
return sentinel;
}
function resolveActivatedBundledPluginPublicSurfaceAccessOrThrow(
params: BundledPluginPublicSurfaceParams,
) {
const access = resolveBundledPluginPublicSurfaceAccess(params);
if (!access.allowed) {
throwForBundledPluginPublicSurfaceAccess({
access,
request: params,
});
}
return access;
}
export function loadBundledPluginPublicSurfaceModuleSync<T extends object>(
params: BundledPluginPublicSurfaceParams,
): T {
const location = resolveFacadeModuleLocation(params);
if (!location) {
throw new Error(
`Unable to resolve bundled plugin public surface ${params.dirName}/${params.artifactBasename}`,
);
}
return loadFacadeModuleAtLocationSync<T>({
location,
trackedPluginId: () => resolveTrackedFacadePluginId(params),
});
}
export function canLoadActivatedBundledPluginPublicSurface(params: {
dirName: string;
artifactBasename: string;
@@ -627,13 +692,7 @@ export function loadActivatedBundledPluginPublicSurfaceModuleSync<T extends obje
dirName: string;
artifactBasename: string;
}): T {
const access = resolveBundledPluginPublicSurfaceAccess(params);
if (!access.allowed) {
const pluginLabel = access.pluginId ?? params.dirName;
throw new Error(
`Bundled plugin public surface access blocked for "${pluginLabel}" via ${params.dirName}/${params.artifactBasename}: ${access.reason ?? "plugin runtime is not activated"}`,
);
}
resolveActivatedBundledPluginPublicSurfaceAccessOrThrow(params);
return loadBundledPluginPublicSurfaceModuleSync<T>(params);
}
@@ -666,3 +725,13 @@ export function resetFacadeRuntimeStateForTest(): void {
cachedFacadeManifestRecordsByKey.clear();
cachedFacadePublicSurfaceAccessByKey.clear();
}
export const __testing = {
evaluateBundledPluginPublicSurfaceAccess,
loadFacadeModuleAtLocationSync,
throwForBundledPluginPublicSurfaceAccess,
resolveActivatedBundledPluginPublicSurfaceAccessOrThrow,
resolveFacadeModuleLocation,
resolveBundledPluginPublicSurfaceAccess,
resolveTrackedFacadePluginId,
};

View File

@@ -2814,38 +2814,6 @@ module.exports = {
expectSetupLoaded: true,
expectedChannels: 1,
},
{
name: "can prefer setupEntry for configured channel loads during startup",
fixture: {
id: "setup-runtime-preferred-test",
label: "Setup Runtime Preferred Test",
packageName: "@openclaw/setup-runtime-preferred-test",
fullBlurb: "full entry should be deferred while startup is still cold",
setupBlurb: "setup runtime preferred",
configured: true,
startupDeferConfiguredChannelFullLoadUntilAfterListen: true,
},
load: ({ pluginDir }: { pluginDir: string }) =>
loadOpenClawPlugins({
cache: false,
preferSetupRuntimeForChannelPlugins: true,
config: {
channels: {
"setup-runtime-preferred-test": {
enabled: true,
token: "configured",
},
},
plugins: {
load: { paths: [pluginDir] },
allow: ["setup-runtime-preferred-test"],
},
},
}),
expectFullLoaded: false,
expectSetupLoaded: true,
expectedChannels: 1,
},
{
name: "does not prefer setupEntry for configured channel loads without startup opt-in",
fixture: {
@@ -2887,6 +2855,26 @@ module.exports = {
expect(registry.channels).toHaveLength(expectedChannels);
});
it("prefers setupEntry for configured channel loads during startup when opted in", () => {
expect(
__testing.shouldLoadChannelPluginInSetupRuntime({
manifestChannels: ["setup-runtime-preferred-test"],
setupSource: "./setup-entry.cjs",
startupDeferConfiguredChannelFullLoadUntilAfterListen: true,
cfg: {
channels: {
"setup-runtime-preferred-test": {
enabled: true,
token: "configured",
},
},
},
env: {},
preferSetupRuntimeForChannelPlugins: true,
}),
).toBe(true);
});
it("blocks before_prompt_build but preserves legacy model overrides when prompt injection is disabled", async () => {
useNoBundledPlugins();
const plugin = writePlugin({

View File

@@ -248,6 +248,7 @@ export const __testing = {
resolvePluginSdkAliasCandidateOrder,
resolvePluginSdkAliasFile,
resolvePluginRuntimeModulePath,
shouldLoadChannelPluginInSetupRuntime,
shouldPreferNativeJiti,
toSafeImportPath,
getCompatibleActivePluginRegistry,