diff --git a/src/plugin-sdk/root-alias.cjs b/src/plugin-sdk/root-alias.cjs index 27ab182d349..2c91cbdb61c 100644 --- a/src/plugin-sdk/root-alias.cjs +++ b/src/plugin-sdk/root-alias.cjs @@ -8,6 +8,7 @@ let diagnosticEventsModule = null; const jitiLoaders = new Map(); const pluginSdkSubpathsCache = new Map(); const pluginSdkPackageNames = ["openclaw/plugin-sdk", "@openclaw/plugin-sdk"]; +const pluginSdkSourceExtensions = [".ts", ".mts", ".js", ".mjs", ".cts", ".cjs"]; const isDistRootAlias = __filename.includes( `${path.sep}dist${path.sep}plugin-sdk${path.sep}root-alias.cjs`, ); @@ -129,7 +130,6 @@ function listPluginSdkExportedSubpaths() { function buildPluginSdkAliasMap(useDist) { const packageRoot = getPackageRoot(); const pluginSdkDir = path.join(packageRoot, useDist ? "dist" : "src", "plugin-sdk"); - const ext = useDist ? ".js" : ".ts"; const normalizeTarget = (target) => process.platform === "win32" ? target.replace(/\\/g, "/") : target; const aliasMap = Object.fromEntries( @@ -137,11 +137,24 @@ function buildPluginSdkAliasMap(useDist) { ); for (const subpath of listPluginSdkExportedSubpaths()) { - const candidate = path.join(pluginSdkDir, `${subpath}${ext}`); - if (fs.existsSync(candidate)) { + if (useDist) { + const candidate = path.join(pluginSdkDir, `${subpath}.js`); + if (fs.existsSync(candidate)) { + for (const packageName of pluginSdkPackageNames) { + aliasMap[`${packageName}/${subpath}`] = normalizeTarget(candidate); + } + } + continue; + } + for (const ext of pluginSdkSourceExtensions) { + const candidate = path.join(pluginSdkDir, `${subpath}${ext}`); + if (!fs.existsSync(candidate)) { + continue; + } for (const packageName of pluginSdkPackageNames) { aliasMap[`${packageName}/${subpath}`] = normalizeTarget(candidate); } + break; } } diff --git a/src/plugins/contracts/plugin-sdk-root-alias.test.ts b/src/plugins/contracts/plugin-sdk-root-alias.test.ts index f4b5dca656e..599c373edf7 100644 --- a/src/plugins/contracts/plugin-sdk-root-alias.test.ts +++ b/src/plugins/contracts/plugin-sdk-root-alias.test.ts @@ -28,6 +28,7 @@ function loadRootAliasWithStubs(options?: { aliasPath?: string; packageExports?: Record; platform?: string; + existingPaths?: string[]; }) { let createJitiCalls = 0; let jitiLoadCalls = 0; @@ -71,6 +72,9 @@ function loadRootAliasWithStubs(options?: { 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: () => @@ -305,6 +309,35 @@ describe("plugin-sdk root alias", () => { ]); }); + 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 distAliasPath = createDistAliasPath();