diff --git a/src/channels/plugins/package-state-probes.test.ts b/src/channels/plugins/package-state-probes.test.ts index e938a9077116..e466575b74d0 100644 --- a/src/channels/plugins/package-state-probes.test.ts +++ b/src/channels/plugins/package-state-probes.test.ts @@ -160,4 +160,53 @@ describe("channel package-state probes", () => { }), ).toBe(true); }); + + it("tries dist-runtime package-state probes before falling back to source", () => { + const root = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-package-state-runtime-")); + tempDirs.push(root); + const sourceRoot = path.join(root, "extensions", "matrix"); + const builtRoot = path.join(root, "dist", "extensions", "matrix"); + const runtimeRoot = path.join(root, "dist-runtime", "extensions", "matrix"); + fs.mkdirSync(sourceRoot, { recursive: true }); + fs.mkdirSync(builtRoot, { recursive: true }); + fs.mkdirSync(runtimeRoot, { recursive: true }); + fs.writeFileSync( + path.join(sourceRoot, "auth-presence.js"), + "throw new Error('source probe should not load');\n", + "utf8", + ); + fs.writeFileSync( + path.join(builtRoot, "auth-presence.js"), + "module.exports.stale = () => false;\n", + "utf8", + ); + fs.writeFileSync( + path.join(runtimeRoot, "auth-presence.js"), + "module.exports.hasAnyMatrixAuth = () => true;\n", + "utf8", + ); + + listChannelCatalogEntriesMock.mockReturnValue([ + { + pluginId: "matrix", + origin: "bundled", + rootDir: sourceRoot, + channel: { + id: "matrix", + persistedAuthState: { + specifier: "./auth-presence", + exportName: "hasAnyMatrixAuth", + }, + }, + } satisfies PluginChannelCatalogEntry, + ]); + + expect( + hasBundledChannelPackageState({ + metadataKey: "persistedAuthState", + channelId: "matrix", + cfg: {}, + }), + ).toBe(true); + }); }); diff --git a/src/channels/plugins/package-state-probes.ts b/src/channels/plugins/package-state-probes.ts index 4cedca43e12d..62791e8a2302 100644 --- a/src/channels/plugins/package-state-probes.ts +++ b/src/channels/plugins/package-state-probes.ts @@ -92,24 +92,25 @@ function resolveSourceBundledPluginRoot(rootDir: string): { }; } -function resolveBuiltBundledPackageStateModule(params: { +function listBuiltBundledPackageStateModules(params: { rootDir: string; specifier: string; -}): ChannelPackageStateModuleLocation | null { +}): ChannelPackageStateModuleLocation[] { const sourceRoot = resolveSourceBundledPluginRoot(params.rootDir); if (!sourceRoot) { - return null; + return []; } + const locations: ChannelPackageStateModuleLocation[] = []; for (const rootDir of [ path.join(sourceRoot.packageRoot, "dist", "extensions", sourceRoot.dirName), path.join(sourceRoot.packageRoot, "dist-runtime", "extensions", sourceRoot.dirName), ]) { const modulePath = resolveExistingPluginModulePath(rootDir, params.specifier); if (fs.existsSync(modulePath) && !isSourceModulePath(modulePath)) { - return { modulePath, rootDir }; + locations.push({ modulePath, rootDir }); } } - return null; + return locations; } function resolveChannelPackageStateModuleLocation(params: { @@ -127,14 +128,11 @@ function listChannelPackageStateModuleLocations(params: { specifier: string; }): ChannelPackageStateModuleLocation[] { const source = resolveChannelPackageStateModuleLocation(params); - const built = resolveBuiltBundledPackageStateModule({ + const built = listBuiltBundledPackageStateModules({ rootDir: params.entry.rootDir, specifier: params.specifier, - }); - if (!built || built.modulePath === source.modulePath) { - return [source]; - } - return [built, source]; + }).filter((location) => location.modulePath !== source.modulePath); + return [...built, source]; } function resolveChannelPackageStateMetadata(