fix(plugins): widen plugin-sdk source alias candidates

This commit is contained in:
Vincent Koc
2026-04-14 18:07:40 +01:00
parent 6821b8bfaa
commit 2cab81d9a7
2 changed files with 84 additions and 22 deletions

View File

@@ -148,9 +148,12 @@ function createPluginRuntimeAliasFixture(params?: { srcBody?: string; distBody?:
return { root, srcFile, distFile };
}
function createPluginSdkAliasTargetFixture() {
function createPluginSdkAliasTargetFixture(params?: {
sourceChannelRuntimeExtension?: ".ts" | ".mts" | ".js" | ".mjs" | ".cts" | ".cjs";
}) {
const sourceChannelRuntimeExtension = params?.sourceChannelRuntimeExtension ?? ".ts";
const fixture = createPluginSdkAliasFixture({
srcFile: "channel-runtime.ts",
srcFile: `channel-runtime${sourceChannelRuntimeExtension}`,
distFile: "channel-runtime.js",
packageExports: {
"./plugin-sdk/channel-runtime": { default: "./dist/plugin-sdk/channel-runtime.js" },
@@ -160,7 +163,18 @@ function createPluginSdkAliasTargetFixture() {
const distRootAlias = path.join(fixture.root, "dist", "plugin-sdk", "root-alias.cjs");
fs.writeFileSync(sourceRootAlias, "module.exports = {};\n", "utf-8");
fs.writeFileSync(distRootAlias, "module.exports = {};\n", "utf-8");
return { fixture, sourceRootAlias, distRootAlias };
return {
fixture,
sourceRootAlias,
distRootAlias,
sourceChannelRuntimePath: path.join(
fixture.root,
"src",
"plugin-sdk",
`channel-runtime${sourceChannelRuntimeExtension}`,
),
distChannelRuntimePath: path.join(fixture.root, "dist", "plugin-sdk", "channel-runtime.js"),
};
}
function writePluginEntry(root: string, relativePath: string) {
@@ -533,7 +547,13 @@ describe("plugin sdk alias helpers", () => {
});
it("builds plugin-sdk aliases from the module being loaded, not the loader location", () => {
const { fixture, sourceRootAlias, distRootAlias } = createPluginSdkAliasTargetFixture();
const {
fixture,
sourceRootAlias,
distRootAlias,
sourceChannelRuntimePath,
distChannelRuntimePath,
} = createPluginSdkAliasTargetFixture();
const sourcePluginEntry = writePluginEntry(
fixture.root,
bundledPluginFile("demo", "src/index.ts"),
@@ -544,7 +564,7 @@ describe("plugin sdk alias helpers", () => {
);
expectPluginSdkAliasTargets(sourceAliases, {
rootAliasPath: sourceRootAlias,
channelRuntimePath: path.join(fixture.root, "src", "plugin-sdk", "channel-runtime.ts"),
channelRuntimePath: sourceChannelRuntimePath,
});
const distPluginEntry = writePluginEntry(
@@ -557,12 +577,12 @@ describe("plugin sdk alias helpers", () => {
);
expectPluginSdkAliasTargets(distAliases, {
rootAliasPath: distRootAlias,
channelRuntimePath: path.join(fixture.root, "dist", "plugin-sdk", "channel-runtime.js"),
channelRuntimePath: distChannelRuntimePath,
});
});
it("applies explicit dist resolution to plugin-sdk subpath aliases too", () => {
const { fixture, distRootAlias } = createPluginSdkAliasTargetFixture();
const { fixture, distRootAlias, distChannelRuntimePath } = createPluginSdkAliasTargetFixture();
const sourcePluginEntry = writePluginEntry(
fixture.root,
bundledPluginFile("demo", "src/index.ts"),
@@ -574,13 +594,38 @@ describe("plugin sdk alias helpers", () => {
expectPluginSdkAliasTargets(distAliases, {
rootAliasPath: distRootAlias,
channelRuntimePath: path.join(fixture.root, "dist", "plugin-sdk", "channel-runtime.js"),
channelRuntimePath: distChannelRuntimePath,
});
});
it("builds source plugin-sdk subpath aliases through the wider source extension family", () => {
const { fixture, sourceRootAlias, sourceChannelRuntimePath } =
createPluginSdkAliasTargetFixture({
sourceChannelRuntimeExtension: ".mts",
});
const sourcePluginEntry = writePluginEntry(
fixture.root,
bundledPluginFile("demo", "src/index.ts"),
);
const sourceAliases = withEnv({ NODE_ENV: undefined }, () =>
buildPluginLoaderAliasMap(sourcePluginEntry),
);
expectPluginSdkAliasTargets(sourceAliases, {
rootAliasPath: sourceRootAlias,
channelRuntimePath: sourceChannelRuntimePath,
});
});
it("resolves plugin-sdk aliases for user-installed plugins via the running openclaw argv hint", () => {
const { externalPluginEntry, externalPluginRoot, fixture, sourceRootAlias } =
createUserInstalledPluginSdkAliasFixture();
const {
externalPluginEntry,
externalPluginRoot,
fixture,
sourceRootAlias,
sourceChannelRuntimePath,
} = createUserInstalledPluginSdkAliasFixture();
const aliases = withCwd(externalPluginRoot, () =>
withEnv({ NODE_ENV: undefined }, () =>
@@ -590,13 +635,18 @@ describe("plugin sdk alias helpers", () => {
expectPluginSdkAliasTargets(aliases, {
rootAliasPath: sourceRootAlias,
channelRuntimePath: path.join(fixture.root, "src", "plugin-sdk", "channel-runtime.ts"),
channelRuntimePath: sourceChannelRuntimePath,
});
});
it("resolves plugin-sdk aliases for user-installed plugins via moduleUrl hint", () => {
const { externalPluginEntry, externalPluginRoot, fixture, sourceRootAlias } =
createUserInstalledPluginSdkAliasFixture();
const {
externalPluginEntry,
externalPluginRoot,
fixture,
sourceRootAlias,
sourceChannelRuntimePath,
} = createUserInstalledPluginSdkAliasFixture();
// Simulate loader.ts passing its own import.meta.url as the moduleUrl hint.
// This covers installations where argv1 does not resolve to the openclaw root
@@ -624,7 +674,7 @@ describe("plugin sdk alias helpers", () => {
expectPluginSdkAliasTargets(aliases, {
rootAliasPath: sourceRootAlias,
channelRuntimePath: path.join(fixture.root, "src", "plugin-sdk", "channel-runtime.ts"),
channelRuntimePath: sourceChannelRuntimePath,
});
});

View File

@@ -252,7 +252,7 @@ export function resolvePluginSdkAliasFile(params: {
const cachedPluginSdkExportedSubpaths = new Map<string, string[]>();
const cachedPluginSdkScopedAliasMaps = new Map<string, Record<string, string>>();
const PLUGIN_SDK_PACKAGE_NAMES = ["openclaw/plugin-sdk", "@openclaw/plugin-sdk"] as const;
const EXTENSION_API_SOURCE_CANDIDATE_EXTENSIONS = [
const PLUGIN_SDK_SOURCE_CANDIDATE_EXTENSIONS = [
".ts",
".mts",
".js",
@@ -321,18 +321,30 @@ export function resolvePluginSdkScopedAliasMap(
moduleUrl: params.moduleUrl,
pluginSdkResolution: params.pluginSdkResolution,
})) {
const candidateMap = {
src: path.join(packageRoot, "src", "plugin-sdk", `${subpath}.ts`),
dist: path.join(packageRoot, "dist", "plugin-sdk", `${subpath}.js`),
} as const;
for (const kind of orderedKinds) {
const candidate = candidateMap[kind];
if (fs.existsSync(candidate)) {
if (kind === "dist") {
const candidate = path.join(packageRoot, "dist", "plugin-sdk", `${subpath}.js`);
if (fs.existsSync(candidate)) {
for (const packageName of PLUGIN_SDK_PACKAGE_NAMES) {
aliasMap[`${packageName}/${subpath}`] = candidate;
}
break;
}
continue;
}
for (const ext of PLUGIN_SDK_SOURCE_CANDIDATE_EXTENSIONS) {
const candidate = path.join(packageRoot, "src", "plugin-sdk", `${subpath}${ext}`);
if (!fs.existsSync(candidate)) {
continue;
}
for (const packageName of PLUGIN_SDK_PACKAGE_NAMES) {
aliasMap[`${packageName}/${subpath}`] = candidate;
}
break;
}
if (Object.prototype.hasOwnProperty.call(aliasMap, `openclaw/plugin-sdk/${subpath}`)) {
break;
}
}
}
cachedPluginSdkScopedAliasMaps.set(cacheKey, aliasMap);
@@ -360,7 +372,7 @@ export function resolveExtensionApiAlias(params: LoaderModuleResolveParams = {})
}
continue;
}
for (const ext of EXTENSION_API_SOURCE_CANDIDATE_EXTENSIONS) {
for (const ext of PLUGIN_SDK_SOURCE_CANDIDATE_EXTENSIONS) {
const candidate = path.join(packageRoot, "src", `extensionAPI${ext}`);
if (fs.existsSync(candidate)) {
return candidate;