diff --git a/extensions/matrix/src/plugin-entry.runtime.js b/extensions/matrix/src/plugin-entry.runtime.js index c34c085bf03..861fcb2bb46 100644 --- a/extensions/matrix/src/plugin-entry.runtime.js +++ b/extensions/matrix/src/plugin-entry.runtime.js @@ -38,6 +38,10 @@ function readPackageJson(packageRoot) { } } +function normalizeLowercaseStringOrEmpty(value) { + return typeof value === "string" ? value.toLowerCase() : ""; +} + function hasTrustedOpenClawRootIndicator(packageRoot, packageJson) { const packageExports = packageJson?.exports ?? {}; if (!Object.prototype.hasOwnProperty.call(packageExports, "./plugin-sdk")) { @@ -45,7 +49,8 @@ function hasTrustedOpenClawRootIndicator(packageRoot, packageJson) { } const hasCliEntryExport = Object.prototype.hasOwnProperty.call(packageExports, "./cli-entry"); const hasOpenClawBin = - (typeof packageJson?.bin === "string" && packageJson.bin.includes("openclaw")) || + (typeof packageJson?.bin === "string" && + normalizeLowercaseStringOrEmpty(packageJson.bin).includes("openclaw")) || (typeof packageJson?.bin === "object" && packageJson.bin !== null && typeof packageJson.bin.openclaw === "string"); diff --git a/extensions/matrix/src/plugin-entry.runtime.test.ts b/extensions/matrix/src/plugin-entry.runtime.test.ts index 60473b4438a..9f370b3c777 100644 --- a/extensions/matrix/src/plugin-entry.runtime.test.ts +++ b/extensions/matrix/src/plugin-entry.runtime.test.ts @@ -107,6 +107,34 @@ function writeOpenClawAliasFixture(fixtureRoot: string, extraExports?: Record, +) { + writeFixtureFile( + fixtureRoot, + "package.json", + JSON.stringify( + { + name: "openclaw", + type: "module", + bin: packageBin, + exports: { + "./plugin-sdk": "./dist/plugin-sdk/index.js", + "./plugin-sdk/group-access": "./dist/plugin-sdk/group-access.js", + }, + }, + null, + 2, + ) + "\n", + ); + writeFixtureFile(fixtureRoot, "src/plugin-sdk/root-alias.cjs", "module.exports = {};\n"); + writeFixtureFile(fixtureRoot, "src/plugin-sdk/group-access.ts", "export {};\n"); + writeFixtureFile(fixtureRoot, "dist/plugin-sdk/index.js", "export {};\n"); + writeFixtureFile(fixtureRoot, "dist/plugin-sdk/root-alias.cjs", "module.exports = {};\n"); + writeFixtureFile(fixtureRoot, "dist/plugin-sdk/group-access.js", "export {};\n"); +} + afterEach(() => { for (const dir of tempDirs.splice(0, tempDirs.length)) { fs.rmSync(dir, { recursive: true, force: true }); @@ -328,3 +356,33 @@ it("ignores nearby untrusted openclaw package stubs when resolving the wrapper r }, }); }, 240_000); + +it("treats string bin hints case-insensitively when trusting wrapper package roots", async () => { + const fixtureRoot = makeFixtureRoot(".tmp-matrix-runtime-bin-root-"); + const wrapperSource = fs.readFileSync( + path.join(REPO_ROOT, "extensions", "matrix", "src", "plugin-entry.runtime.js"), + "utf8", + ); + + delete matrixWrapperGlobal.__openclawMatrixWrapperJitiOptions; + writeTrustedOpenClawBinFixture(fixtureRoot, "OpenClaw.MJS"); + writeCapturingJitiFixture(fixtureRoot); + writeFixtureFile(fixtureRoot, "extensions/matrix/src/plugin-entry.runtime.js", wrapperSource); + writeFixtureFile( + fixtureRoot, + "extensions/matrix/plugin-entry.handlers.runtime.js", + PACKAGED_RUNTIME_STUB, + ); + + const wrapperUrl = pathToFileURL( + path.join(fixtureRoot, "extensions", "matrix", "src", "plugin-entry.runtime.js"), + ); + await import(`${wrapperUrl.href}?t=${Date.now()}`); + + expect(matrixWrapperGlobal.__openclawMatrixWrapperJitiOptions).toMatchObject({ + alias: { + "openclaw/plugin-sdk": path.join(fixtureRoot, "src", "plugin-sdk", "root-alias.cjs"), + "@openclaw/plugin-sdk": path.join(fixtureRoot, "src", "plugin-sdk", "root-alias.cjs"), + }, + }); +}, 240_000);