Plugins: resolve sdk aliases from the running CLI

This commit is contained in:
scoootscooob
2026-03-24 10:22:08 -07:00
committed by scoootscooob
parent 8633c7fa73
commit f163759167
2 changed files with 48 additions and 6 deletions

View File

@@ -60,6 +60,16 @@ function withCwd<T>(cwd: string, run: () => T): T {
}
}
function withArgv1<T>(argv1: string, run: () => T): T {
const originalArgv = process.argv;
process.argv = [originalArgv[0] ?? "node", argv1, ...originalArgv.slice(2)];
try {
return run();
} finally {
process.argv = originalArgv;
}
}
function createPluginSdkAliasFixture(params?: {
srcFile?: string;
distFile?: string;
@@ -461,6 +471,35 @@ describe("plugin sdk alias helpers", () => {
);
});
it("resolves plugin-sdk aliases for user-installed plugins via the running openclaw argv hint", () => {
const fixture = createPluginSdkAliasFixture({
srcFile: "channel-runtime.ts",
distFile: "channel-runtime.js",
packageExports: {
"./plugin-sdk/channel-runtime": { default: "./dist/plugin-sdk/channel-runtime.js" },
},
});
const sourceRootAlias = path.join(fixture.root, "src", "plugin-sdk", "root-alias.cjs");
fs.writeFileSync(sourceRootAlias, "module.exports = {};\n", "utf-8");
const externalPluginRoot = path.join(makeTempDir(), ".openclaw", "extensions", "demo");
const externalPluginEntry = path.join(externalPluginRoot, "index.ts");
mkdirSafe(externalPluginRoot);
fs.writeFileSync(externalPluginEntry, 'export const plugin = "demo";\n', "utf-8");
const aliases = withArgv1(path.join(fixture.root, "openclaw.mjs"), () =>
withCwd(externalPluginRoot, () =>
withEnv({ NODE_ENV: undefined }, () => buildPluginLoaderAliasMap(externalPluginEntry)),
),
);
expect(fs.realpathSync(aliases["openclaw/plugin-sdk"] ?? "")).toBe(
fs.realpathSync(sourceRootAlias),
);
expect(fs.realpathSync(aliases["openclaw/plugin-sdk/channel-runtime"] ?? "")).toBe(
fs.realpathSync(path.join(fixture.root, "src", "plugin-sdk", "channel-runtime.ts")),
);
});
it("does not resolve plugin-sdk alias files from cwd fallback when package root is not an OpenClaw root", () => {
const fixture = createPluginSdkAliasFixture({
srcFile: "channel-runtime.ts",

View File

@@ -207,9 +207,11 @@ export function resolvePluginSdkAliasFile(params: {
const cachedPluginSdkExportedSubpaths = new Map<string, string[]>();
const cachedPluginSdkScopedAliasMaps = new Map<string, Record<string, string>>();
export function listPluginSdkExportedSubpaths(params: { modulePath?: string } = {}): string[] {
export function listPluginSdkExportedSubpaths(
params: { modulePath?: string; argv1?: string } = {},
): string[] {
const modulePath = params.modulePath ?? fileURLToPath(import.meta.url);
const packageRoot = resolveLoaderPluginSdkPackageRoot({ modulePath });
const packageRoot = resolveLoaderPluginSdkPackageRoot({ modulePath, argv1: params.argv1 });
if (!packageRoot) {
return [];
}
@@ -223,10 +225,10 @@ export function listPluginSdkExportedSubpaths(params: { modulePath?: string } =
}
export function resolvePluginSdkScopedAliasMap(
params: { modulePath?: string } = {},
params: { modulePath?: string; argv1?: string } = {},
): Record<string, string> {
const modulePath = params.modulePath ?? fileURLToPath(import.meta.url);
const packageRoot = resolveLoaderPluginSdkPackageRoot({ modulePath });
const packageRoot = resolveLoaderPluginSdkPackageRoot({ modulePath, argv1: params.argv1 });
if (!packageRoot) {
return {};
}
@@ -240,7 +242,7 @@ export function resolvePluginSdkScopedAliasMap(
return cached;
}
const aliasMap: Record<string, string> = {};
for (const subpath of listPluginSdkExportedSubpaths({ modulePath })) {
for (const subpath of listPluginSdkExportedSubpaths({ modulePath, argv1: params.argv1 })) {
const candidateMap = {
src: path.join(packageRoot, "src", "plugin-sdk", `${subpath}.ts`),
dist: path.join(packageRoot, "dist", "plugin-sdk", `${subpath}.js`),
@@ -290,12 +292,13 @@ export function buildPluginLoaderAliasMap(modulePath: string): Record<string, st
srcFile: "root-alias.cjs",
distFile: "root-alias.cjs",
modulePath,
argv1: process.argv[1],
});
const extensionApiAlias = resolveExtensionApiAlias({ modulePath });
return {
...(extensionApiAlias ? { "openclaw/extension-api": extensionApiAlias } : {}),
...(pluginSdkAlias ? { "openclaw/plugin-sdk": pluginSdkAlias } : {}),
...resolvePluginSdkScopedAliasMap({ modulePath }),
...resolvePluginSdkScopedAliasMap({ modulePath, argv1: process.argv[1] }),
};
}