import fs from "node:fs" ;
import { createRequire } from "node:module" ;
import path from "node:path" ;
import { fileURLToPath } from "node:url" ;
import vm from "node:vm" ;
import { describe, expect, it } from "vitest" ;
const require = createRequire(import .meta.url);
const rootAliasPath = fileURLToPath(new URL("../../plugin-sdk/root-alias.cjs" , import .meta.url));
const rootSdk = require(rootAliasPath) as Record<string, unknown>;
const rootAliasSource = fs.readFileSync(rootAliasPath, "utf-8" );
const packageJsonPath = fileURLToPath(new URL("../../../package.json" , import .meta.url));
type EmptySchema = {
safeParse: (value: unknown) =>
| { success: true ; data?: unknown }
| {
success: false ;
error: { issues: Array<{ path: Array<string | number>; message: string }> };
};
};
function loadRootAliasWithStubs(options?: {
distExists?: boolean ;
distEntries?: string[];
env?: Record<string, string | undefined>;
monolithicExports?: Record<string | symbol, unknown>;
aliasPath?: string;
packageExports?: Record<string, unknown>;
platform?: string;
existingPaths?: string[];
privateLocalOnlySubpaths?: unknown;
}) {
let createJitiCalls = 0 ;
let jitiLoadCalls = 0 ;
const createJitiOptions: Record<string, unknown>[] = [];
const loadedSpecifiers: string[] = [];
const monolithicExports = options?.monolithicExports ?? {
slowHelper: () => "loaded" ,
};
const wrapper = vm.runInNewContext(
`(function (exports, require, module, __filename, __dirname) {${rootAliasSource}\n})`,
{
process: {
env: options?.env ?? {},
platform: options?.platform ?? "darwin" ,
},
},
{ filename: rootAliasPath },
) as (
exports: Record<string, unknown>,
require: NodeJS.Require,
module: { exports: Record<string, unknown> },
__filename: string,
__dirname: string,
) => void ;
const module = { exports: {} as Record<string, unknown> };
const aliasPath = options?.aliasPath ?? rootAliasPath;
const localRequire = ((id: string) => {
if (id === "node:path" ) {
return path;
}
if (id === "node:fs" ) {
return {
readFileSync: (targetPath: string) => {
if (
targetPath.endsWith(
path.join("scripts" , "lib" , "plugin-sdk-private-local-only-subpaths.json" ),
)
) {
return JSON.stringify(options?.privateLocalOnlySubpaths ?? []);
}
return JSON.stringify({
exports: {
"./plugin-sdk/group-access" : { default : "./dist/plugin-sdk/group-access.js" },
...options?.packageExports,
},
});
},
existsSync: (targetPath: string) => {
if (targetPath.endsWith(path.join("dist" , "infra" , "diagnostic-events.js" ))) {
return options?.distExists ?? false ;
}
if (options?.existingPaths?.includes(targetPath)) {
return true ;
}
return options?.distExists ?? false ;
},
readdirSync: () =>
(options?.distEntries ?? []).map((name) => ({
name,
isFile: () => true ,
isDirectory: () => false ,
})),
};
}
if (id === "jiti" ) {
return {
createJiti(_filename: string, jitiOptions?: Record<string, unknown>) {
createJitiCalls += 1 ;
createJitiOptions.push(jitiOptions ?? {});
return (specifier: string) => {
jitiLoadCalls += 1 ;
loadedSpecifiers.push(specifier);
return monolithicExports;
};
},
};
}
throw new Error(`unexpected require: ${id}`);
}) as NodeJS.Require;
wrapper(module.exports, localRequire, module, aliasPath, path.dirname(aliasPath));
return {
moduleExports: module.exports,
get createJitiCalls() {
return createJitiCalls;
},
get jitiLoadCalls() {
return jitiLoadCalls;
},
get createJitiOptions() {
return createJitiOptions;
},
loadedSpecifiers,
};
}
function createPackageRoot() {
return path.dirname(path.dirname(rootAliasPath));
}
function createDistAliasPath() {
return path.join(createPackageRoot(), "dist" , "plugin-sdk" , "root-alias.cjs" );
}
function loadDiagnosticEventsAlias(distEntries: string[]) {
return loadRootAliasWithStubs({
aliasPath: createDistAliasPath(),
distExists: false ,
distEntries,
monolithicExports: {
r: (): (() => void ) => () => undefined,
slowHelper: (): string => "loaded" ,
},
});
}
function expectDiagnosticEventAccessor(lazyModule: ReturnType<typeof loadRootAliasWithStubs>) {
expect(
typeof (lazyModule.moduleExports.onDiagnosticEvent as (listener: () => void ) => () => void )(
() => undefined,
),
).toBe("function" );
}
describe("plugin-sdk root alias" , () => {
it("exposes the fast empty config schema helper" , () => {
const factory = rootSdk.emptyPluginConfigSchema as (() => EmptySchema) | undefined;
expect(typeof factory).toBe("function" );
if (!factory) {
return ;
}
const schema = factory();
expect(schema.safeParse(undefined)).toEqual({ success: true , data: undefined });
expect(schema.safeParse({})).toEqual({ success: true , data: {} });
const parsed = schema.safeParse({ invalid: true });
expect(parsed.success).toBe(false );
});
it("does not load the monolithic sdk for fast helpers" , () => {
const lazyModule = loadRootAliasWithStubs();
const lazyRootSdk = lazyModule.moduleExports;
const factory = lazyRootSdk.emptyPluginConfigSchema as (() => EmptySchema) | undefined;
expect(lazyModule.createJitiCalls).toBe(0 );
expect(lazyModule.jitiLoadCalls).toBe(0 );
expect(typeof factory).toBe("function" );
expect(factory?.().safeParse({})).toEqual({ success: true , data: {} });
expect(lazyModule.createJitiCalls).toBe(0 );
expect(lazyModule.jitiLoadCalls).toBe(0 );
});
it("does not load the monolithic sdk for promise-like or symbol reflection probes" , () => {
const lazyModule = loadRootAliasWithStubs();
const lazyRootSdk = lazyModule.moduleExports;
expect("then" in lazyRootSdk).toBe(false );
expect(Reflect.get(lazyRootSdk, Symbol.toStringTag)).toBeUndefined();
expect(Object.getOwnPropertyDescriptor(lazyRootSdk, Symbol.toStringTag)).toBeUndefined();
expect(lazyModule.createJitiCalls).toBe(0 );
expect(lazyModule.jitiLoadCalls).toBe(0 );
});
it("loads legacy root exports on demand and preserves reflection" , () => {
const lazyModule = loadRootAliasWithStubs({
monolithicExports: {
slowHelper: (): string => "loaded" ,
},
});
const lazyRootSdk = lazyModule.moduleExports;
expect(lazyModule.createJitiCalls).toBe(0 );
expect("slowHelper" in lazyRootSdk).toBe(true );
expect(lazyModule.createJitiCalls).toBe(1 );
expect(lazyModule.jitiLoadCalls).toBe(1 );
expect(lazyModule.createJitiOptions.at(-1 )?.tryNative).toBe(false );
expect((lazyRootSdk.slowHelper as () => string)()).toBe("loaded" );
expect(Object.keys(lazyRootSdk)).toContain("slowHelper" );
expect(Object.getOwnPropertyDescriptor(lazyRootSdk, "slowHelper" )).toBeDefined();
});
it.each([
{
name: "prefers source loading when the source root alias runs in development" ,
options: {
distExists: true ,
env: { NODE_ENV: "development" },
monolithicExports: {
slowHelper: (): string => "loaded" ,
},
},
expectedTryNative: false ,
},
{
name: "prefers native loading when compat resolves to dist" ,
options: {
distExists: true ,
env: { NODE_ENV: "production" },
monolithicExports: {
slowHelper: (): string => "loaded" ,
},
},
expectedTryNative: true ,
},
{
name: "prefers source loading under vitest even when compat resolves to dist" ,
options: {
distExists: true ,
env: { VITEST: "1" },
monolithicExports: {
slowHelper: (): string => "loaded" ,
},
},
expectedTryNative: false ,
},
{
name: "prefers source loading on Windows even when compat resolves to dist" ,
options: {
distExists: true ,
env: { NODE_ENV: "production" },
platform: "win32" ,
monolithicExports: {
slowHelper: (): string => "loaded" ,
},
},
expectedTryNative: false ,
},
])("$name" , ({ options, expectedTryNative }) => {
const lazyModule = loadRootAliasWithStubs(options);
expect((lazyModule.moduleExports.slowHelper as () => string)()).toBe("loaded" );
expect(lazyModule.createJitiOptions.at(-1 )?.tryNative).toBe(expectedTryNative);
});
it("falls back to src files even when the alias itself is loaded from dist" , () => {
const packageRoot = createPackageRoot();
const distAliasPath = createDistAliasPath();
const lazyModule = loadRootAliasWithStubs({
aliasPath: distAliasPath,
distExists: false ,
monolithicExports: {
onDiagnosticEvent: (): (() => void ) => () => undefined,
slowHelper: (): string => "loaded" ,
},
});
expect((lazyModule.moduleExports.slowHelper as () => string)()).toBe("loaded" );
expect(lazyModule.loadedSpecifiers).toContain(
path.join(packageRoot, "src" , "plugin-sdk" , "compat.ts" ),
);
expect(
typeof (lazyModule.moduleExports.onDiagnosticEvent as (listener: () => void ) => () => void )(
() => undefined,
),
).toBe("function" );
expect(lazyModule.loadedSpecifiers).toContain(
path.join(packageRoot, "src" , "infra" , "diagnostic-events.ts" ),
);
});
it("builds scoped and unscoped plugin-sdk aliases for jiti loads" , () => {
const lazyModule = loadRootAliasWithStubs({
distExists: true ,
monolithicExports: {
slowHelper: (): string => "loaded" ,
},
});
expect((lazyModule.moduleExports.slowHelper as () => string)()).toBe("loaded" );
expect(lazyModule.createJitiOptions.at(-1 )?.alias).toMatchObject({
"openclaw/plugin-sdk" : rootAliasPath,
"@openclaw/plugin-sdk" : rootAliasPath,
"openclaw/plugin-sdk/group-access" : expect.stringContaining(
path.join("src" , "plugin-sdk" , "group-access.ts" ),
),
"@openclaw/plugin-sdk/group-access" : expect.stringContaining(
path.join("src" , "plugin-sdk" , "group-access.ts" ),
),
});
});
it("keeps bootstrap plugin-sdk aliases deterministic and ignores unsafe subpaths" , () => {
const lazyModule = loadRootAliasWithStubs({
distExists: true ,
packageExports: {
"./plugin-sdk/zeta" : { default : "./dist/plugin-sdk/zeta.js" },
"./plugin-sdk/../escape" : { default : "./dist/plugin-sdk/escape.js" },
"./plugin-sdk/alpha" : { default : "./dist/plugin-sdk/alpha.js" },
},
monolithicExports: {
slowHelper: (): string => "loaded" ,
},
});
expect((lazyModule.moduleExports.slowHelper as () => string)()).toBe("loaded" );
const aliasKeys = Object.keys(
(lazyModule.createJitiOptions.at(-1 )?.alias ?? {}) as Record<string, string>,
);
expect(aliasKeys).toEqual([
"openclaw/plugin-sdk/alpha" ,
"@openclaw/plugin-sdk/alpha" ,
"openclaw/plugin-sdk/group-access" ,
"@openclaw/plugin-sdk/group-access" ,
"openclaw/plugin-sdk/zeta" ,
"@openclaw/plugin-sdk/zeta" ,
"openclaw/plugin-sdk" ,
"@openclaw/plugin-sdk" ,
]);
});
it("ignores unsafe private local-only plugin-sdk subpaths in the CJS root alias" , () => {
const packageRoot = path.dirname(path.dirname(path.dirname(rootAliasPath)));
const lazyModule = loadRootAliasWithStubs({
env: { OPENCLAW_ENABLE_PRIVATE_QA_CLI: "1" },
privateLocalOnlySubpaths: ["qa-lab" , "../escape" , "nested/path" ],
existingPaths: [path.join(packageRoot, "src" , "plugin-sdk" , "qa-lab.ts" )],
monolithicExports: {
slowHelper: (): string => "loaded" ,
},
});
expect((lazyModule.moduleExports.slowHelper as () => string)()).toBe("loaded" );
const aliasMap = (lazyModule.createJitiOptions.at(-1 )?.alias ?? {}) as Record<string, string>;
expect(aliasMap["openclaw/plugin-sdk/qa-lab" ]).toBe(
path.join(packageRoot, "src" , "plugin-sdk" , "qa-lab.ts" ),
);
expect(aliasMap["@openclaw/plugin-sdk/qa-lab" ]).toBe(
path.join(packageRoot, "src" , "plugin-sdk" , "qa-lab.ts" ),
);
expect(aliasMap).not.toHaveProperty("openclaw/plugin-sdk/../escape" );
expect(aliasMap).not.toHaveProperty("openclaw/plugin-sdk/nested/path" );
});
it("builds source plugin-sdk subpath aliases through the wider source extension family" , () => {
const packageRoot = path.dirname(path.dirname(path.dirname(rootAliasPath)));
const lazyModule = loadRootAliasWithStubs({
packageExports: {
"./plugin-sdk/channel-runtime" : { default : "./dist/plugin-sdk/channel-runtime.js" },
},
existingPaths: [path.join(packageRoot, "src" , "plugin-sdk" , "channel-runtime.mts" )],
monolithicExports: {
slowHelper: (): string => "loaded" ,
},
});
expect((lazyModule.moduleExports.slowHelper as () => string)()).toBe("loaded" );
expect(lazyModule.createJitiOptions.at(-1 )?.alias).toMatchObject({
"openclaw/plugin-sdk/channel-runtime" : path.join(
packageRoot,
"src" ,
"plugin-sdk" ,
"channel-runtime.mts" ,
),
"@openclaw/plugin-sdk/channel-runtime" : path.join(
packageRoot,
"src" ,
"plugin-sdk" ,
"channel-runtime.mts" ,
),
});
});
it("prefers hashed dist diagnostic events chunks before falling back to src" , () => {
const packageRoot = createPackageRoot();
const lazyModule = loadDiagnosticEventsAlias(["diagnostic-events-W3Hz61fI.js" ]);
expectDiagnosticEventAccessor(lazyModule);
expect(lazyModule.loadedSpecifiers).toContain(
path.join(packageRoot, "dist" , "diagnostic-events-W3Hz61fI.js" ),
);
expect(lazyModule.loadedSpecifiers).not.toContain(
path.join(packageRoot, "src" , "infra" , "diagnostic-events.ts" ),
);
});
it("chooses hashed dist diagnostic events chunks deterministically" , () => {
const packageRoot = createPackageRoot();
const lazyModule = loadDiagnosticEventsAlias([
"diagnostic-events-zeta.js" ,
"diagnostic-events-alpha.js" ,
]);
expectDiagnosticEventAccessor(lazyModule);
expect(lazyModule.loadedSpecifiers).toContain(
path.join(packageRoot, "dist" , "diagnostic-events-alpha.js" ),
);
expect(lazyModule.loadedSpecifiers).not.toContain(
path.join(packageRoot, "dist" , "diagnostic-events-zeta.js" ),
);
});
it.each([
{
name: "forwards delegateCompactionToRuntime through the compat-backed root alias" ,
exportName: "delegateCompactionToRuntime" ,
exportValue: () => "delegated" ,
expectIdentity: true ,
assertForwarded: (value: unknown) => {
expect(typeof value).toBe("function" );
expect((value as () => string)()).toBe("delegated" );
},
},
{
name: "forwards onDiagnosticEvent through the compat-backed root alias" ,
exportName: "onDiagnosticEvent" ,
exportValue: () => () => undefined,
expectIdentity: false ,
assertForwarded: (value: unknown) => {
expect(typeof value).toBe("function" );
expect(typeof (value as (listener: () => void ) => () => void )(() => undefined)).toBe(
"function" ,
);
},
},
])("$name" , ({ exportName, exportValue, expectIdentity, assertForwarded }) => {
const lazyModule = loadRootAliasWithStubs({
monolithicExports: {
[exportName]: exportValue,
},
});
const forwarded = lazyModule.moduleExports[exportName];
assertForwarded(forwarded);
if (expectIdentity) {
expect(forwarded).toBe(exportValue);
}
expect(exportName in lazyModule.moduleExports).toBe(true );
});
it("loads legacy root exports through the merged root wrapper" , { timeout: 240 _000 }, () => {
expect(typeof rootSdk.resolveControlCommandGate).toBe("function" );
expect(typeof rootSdk.onDiagnosticEvent).toBe("function" );
expect(typeof rootSdk.default ).toBe("object" );
expect(rootSdk.default ).toBe(rootSdk);
expect(rootSdk.__esModule).toBe(true );
});
it("does not publish removed channel-specific plugin-sdk subpaths" , () => {
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8" )) as {
exports?: Record<string, unknown>;
};
expect(packageJson.exports?.["./plugin-sdk/discord" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/slack" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/signal" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/telegram-core" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/discord-runtime-surface" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/discord-thread-bindings" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/discord-timeouts" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/discord-account" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/discord-session-key" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/discord-surface" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/whatsapp" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/signal-account" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/signal-surface" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/slack-account" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/slack-runtime-surface" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/slack-surface" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/slack-target-parser" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/slack-targets" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/telegram-account" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/telegram-allow-from" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/telegram-surface" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/whatsapp-auth-presence" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/whatsapp-core" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/whatsapp-shared" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/whatsapp-surface" ]).toBeUndefined();
expect(packageJson.exports?.["./plugin-sdk/whatsapp-targets" ]).toBeUndefined();
});
it("preserves reflection semantics for lazily resolved exports" , { timeout: 240 _000 }, () => {
expect("resolveControlCommandGate" in rootSdk).toBe(true );
expect("onDiagnosticEvent" in rootSdk).toBe(true );
const keys = Object.keys(rootSdk);
expect(keys).toContain("resolveControlCommandGate" );
expect(keys).toContain("onDiagnosticEvent" );
const descriptor = Object.getOwnPropertyDescriptor(rootSdk, "resolveControlCommandGate" );
expect(descriptor).toBeDefined();
expect(Object.getOwnPropertyDescriptor(rootSdk, "onDiagnosticEvent" )).toBeDefined();
});
});
Messung V0.5 in Prozent C=92 H=93 G=92
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-04)
¤
*© Formatika GbR, Deutschland