mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:20:43 +00:00
fix(plugins): reject invalid inferred package runtimes
This commit is contained in:
@@ -61,6 +61,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- Plugins/packages: reject inferred built runtime entries that exist but fail package-boundary checks instead of falling back to TypeScript source for installed packages. Thanks @vincentkoc.
|
||||
- Plugins/loader: do not retry native-loaded JavaScript plugin modules through the source transformer after native evaluation has already reached a missing dependency, avoiding duplicate top-level side effects. Thanks @vincentkoc.
|
||||
- Plugins/packages: reject blank `openclaw.runtimeExtensions` entries instead of silently ignoring them and falling back to inferred TypeScript runtime entries. Thanks @vincentkoc.
|
||||
- Doctor/plugins: remove stale managed npm plugin shadow entries from the managed package lock as well as `package.json` and `node_modules`, so future npm operations do not keep referencing repaired bundled-plugin shadows. Thanks @vincentkoc.
|
||||
|
||||
@@ -1505,6 +1505,39 @@ describe("discoverOpenClawPlugins", () => {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "rejects hardlinked inferred built runtime entries instead of falling back to source",
|
||||
expectedDiagnostic: "escapes" as const,
|
||||
expectedId: "pack",
|
||||
setup: (stateDir: string) => {
|
||||
if (process.platform === "win32") {
|
||||
return false;
|
||||
}
|
||||
const globalExt = path.join(stateDir, "extensions", "pack");
|
||||
const outsideDir = path.join(stateDir, "outside");
|
||||
const outsideFile = path.join(outsideDir, "index.js");
|
||||
const linkedFile = path.join(globalExt, "dist", "index.js");
|
||||
mkdirSafe(path.join(globalExt, "src"));
|
||||
mkdirSafe(path.dirname(linkedFile));
|
||||
mkdirSafe(outsideDir);
|
||||
fs.writeFileSync(path.join(globalExt, "src", "index.ts"), "export default {}", "utf-8");
|
||||
fs.writeFileSync(outsideFile, "export default {}", "utf-8");
|
||||
try {
|
||||
fs.linkSync(outsideFile, linkedFile);
|
||||
} catch (err) {
|
||||
if ((err as NodeJS.ErrnoException).code === "EXDEV") {
|
||||
return false;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
writePluginPackageManifest({
|
||||
packageDir: globalExt,
|
||||
packageName: "@openclaw/pack",
|
||||
extensions: ["./src/index.ts"],
|
||||
});
|
||||
return true;
|
||||
},
|
||||
},
|
||||
] as const)("$name", async ({ setup, expectedDiagnostic, expectedId }) => {
|
||||
const stateDir = makeTempDir();
|
||||
await expectRejectedPackageExtensionEntry({
|
||||
|
||||
@@ -434,19 +434,20 @@ function resolveSafePackageEntry(params: {
|
||||
return { relativePath: path.relative(params.packageDir, absolutePath).replace(/\\/g, "/") };
|
||||
}
|
||||
|
||||
function resolveExistingPackageEntrySource(params: {
|
||||
function resolveOptionalExistingPackageEntrySource(params: {
|
||||
packageDir: string;
|
||||
packageRootRealPath?: string;
|
||||
entryPath: string;
|
||||
sourceLabel: string;
|
||||
diagnostics: PluginDiagnostic[];
|
||||
rejectHardlinks?: boolean;
|
||||
}): string | null {
|
||||
}): { status: "missing" } | { status: "invalid" } | { status: "resolved"; source: string } {
|
||||
const source = path.resolve(params.packageDir, params.entryPath);
|
||||
if (!fs.existsSync(source)) {
|
||||
return null;
|
||||
return { status: "missing" };
|
||||
}
|
||||
return resolvePackageEntrySource(params);
|
||||
const resolved = resolvePackageEntrySource(params);
|
||||
return resolved ? { status: "resolved", source: resolved } : { status: "invalid" };
|
||||
}
|
||||
|
||||
function resolvePackageRuntimeEntrySource(params: {
|
||||
@@ -499,7 +500,7 @@ function resolvePackageRuntimeEntrySource(params: {
|
||||
if (shouldInferBuiltRuntimeEntry(params.origin)) {
|
||||
const builtEntryCandidates = listBuiltRuntimeEntryCandidates(safeEntry.relativePath);
|
||||
for (const candidate of builtEntryCandidates) {
|
||||
const runtimeSource = resolveExistingPackageEntrySource({
|
||||
const runtimeSource = resolveOptionalExistingPackageEntrySource({
|
||||
packageDir: params.packageDir,
|
||||
...(params.packageRootRealPath !== undefined
|
||||
? { packageRootRealPath: params.packageRootRealPath }
|
||||
@@ -509,8 +510,11 @@ function resolvePackageRuntimeEntrySource(params: {
|
||||
diagnostics: params.diagnostics,
|
||||
rejectHardlinks: params.rejectHardlinks,
|
||||
});
|
||||
if (runtimeSource) {
|
||||
return runtimeSource;
|
||||
if (runtimeSource.status === "resolved") {
|
||||
return runtimeSource.source;
|
||||
}
|
||||
if (runtimeSource.status === "invalid") {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (
|
||||
|
||||
Reference in New Issue
Block a user