From 817f0cd6c8380435b3d04c1fcacd7e77d371c31c Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 17 May 2026 02:33:28 +0800 Subject: [PATCH] fix(plugins): preserve bundled source overlay probes --- .../plugins/package-state-probes.test.ts | 53 +++++++++++++++++++ src/channels/plugins/package-state-probes.ts | 4 ++ 2 files changed, 57 insertions(+) diff --git a/src/channels/plugins/package-state-probes.test.ts b/src/channels/plugins/package-state-probes.test.ts index e466575b74d0..fb7f42093c23 100644 --- a/src/channels/plugins/package-state-probes.test.ts +++ b/src/channels/plugins/package-state-probes.test.ts @@ -9,11 +9,17 @@ import { } from "./package-state-probes.js"; const listChannelCatalogEntriesMock = vi.hoisted(() => vi.fn()); +const isBundledSourceOverlayPathMock = vi.hoisted(() => + vi.fn((_params: { sourcePath: string }) => false), +); const tempDirs: string[] = []; vi.mock("../../plugins/channel-catalog-registry.js", () => ({ listChannelCatalogEntries: listChannelCatalogEntriesMock, })); +vi.mock("../../plugins/bundled-source-overlays.js", () => ({ + isBundledSourceOverlayPath: isBundledSourceOverlayPathMock, +})); function makeBundledChannelCatalogEntry(params: { pluginId: string; @@ -43,6 +49,8 @@ function removeTempDirs() { beforeEach(() => { removeTempDirs(); listChannelCatalogEntriesMock.mockReset(); + isBundledSourceOverlayPathMock.mockReset(); + isBundledSourceOverlayPathMock.mockReturnValue(false); }); afterEach(() => { @@ -161,6 +169,51 @@ describe("channel package-state probes", () => { ).toBe(true); }); + it("preserves source overlay precedence over packaged package-state probes", () => { + const root = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-package-state-overlay-")); + tempDirs.push(root); + const sourceRoot = path.join(root, "extensions", "matrix"); + const builtRoot = path.join(root, "dist", "extensions", "matrix"); + fs.mkdirSync(sourceRoot, { recursive: true }); + fs.mkdirSync(builtRoot, { recursive: true }); + fs.writeFileSync( + path.join(sourceRoot, "auth-presence.js"), + "module.exports.hasAnyMatrixAuth = () => true;\n", + "utf8", + ); + fs.writeFileSync( + path.join(builtRoot, "auth-presence.js"), + "module.exports.hasAnyMatrixAuth = () => false;\n", + "utf8", + ); + isBundledSourceOverlayPathMock.mockImplementation( + ({ sourcePath }: { sourcePath: string }) => path.resolve(sourcePath) === sourceRoot, + ); + + 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); + }); + 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); diff --git a/src/channels/plugins/package-state-probes.ts b/src/channels/plugins/package-state-probes.ts index 62791e8a2302..b602df10d0b8 100644 --- a/src/channels/plugins/package-state-probes.ts +++ b/src/channels/plugins/package-state-probes.ts @@ -3,6 +3,7 @@ import path from "node:path"; import type { OpenClawConfig } from "../../config/types.openclaw.js"; import { formatErrorMessage } from "../../infra/errors.js"; import { createSubsystemLogger } from "../../logging/subsystem.js"; +import { isBundledSourceOverlayPath } from "../../plugins/bundled-source-overlays.js"; import { listChannelCatalogEntries, type PluginChannelCatalogEntry, @@ -96,6 +97,9 @@ function listBuiltBundledPackageStateModules(params: { rootDir: string; specifier: string; }): ChannelPackageStateModuleLocation[] { + if (isBundledSourceOverlayPath({ sourcePath: params.rootDir })) { + return []; + } const sourceRoot = resolveSourceBundledPluginRoot(params.rootDir); if (!sourceRoot) { return [];