mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 17:20:45 +00:00
fix: discover source-only plugins in checkouts
This commit is contained in:
@@ -9,13 +9,15 @@ import {
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
import { detectBundleManifestFormat, loadBundleManifest } from "./bundle-manifest.js";
|
||||
import { resolveSourceCheckoutDependencyDiagnostic } from "./bundled-dir.js";
|
||||
import { resolvePackagedBundledLoadPathAlias } from "./bundled-load-path-aliases.js";
|
||||
import {
|
||||
buildLegacyBundledRootPath,
|
||||
resolvePackagedBundledLoadPathAlias,
|
||||
} from "./bundled-load-path-aliases.js";
|
||||
import { listBundledSourceOverlayDirs } from "./bundled-source-overlays.js";
|
||||
import type { PluginBundleFormat, PluginDiagnostic, PluginFormat } from "./manifest-types.js";
|
||||
import {
|
||||
DEFAULT_PLUGIN_ENTRY_CANDIDATES,
|
||||
getPackageManifestMetadata,
|
||||
isPackageIncludedInCoreBundle,
|
||||
loadPluginManifest,
|
||||
type PluginManifest,
|
||||
resolvePackageExtensionEntries,
|
||||
@@ -627,10 +629,6 @@ function discoverInDirectory(params: {
|
||||
const rejectHardlinks = params.origin !== "bundled";
|
||||
const fullPathRealPath = safeRealpathSync(fullPath, params.realpathCache) ?? undefined;
|
||||
const manifest = readPackageManifest(fullPath, rejectHardlinks, fullPathRealPath);
|
||||
const packageManifest = getPackageManifestMetadata(manifest ?? undefined);
|
||||
if (params.origin === "bundled" && !isPackageIncludedInCoreBundle(packageManifest)) {
|
||||
continue;
|
||||
}
|
||||
const extensionResolution = resolvePackageExtensionEntries(manifest ?? undefined);
|
||||
const extensions = extensionResolution.status === "ok" ? extensionResolution.entries : [];
|
||||
const manifestId = resolveIdHintManifestId(fullPath, rejectHardlinks, fullPathRealPath);
|
||||
@@ -725,6 +723,61 @@ function discoverInDirectory(params: {
|
||||
}
|
||||
}
|
||||
|
||||
function hasDiscoverablePluginTree(pluginsDir: string): boolean {
|
||||
try {
|
||||
return fs.readdirSync(pluginsDir, { withFileTypes: true }).some((entry) => {
|
||||
if (!entry.isDirectory()) {
|
||||
return false;
|
||||
}
|
||||
const pluginDir = path.join(pluginsDir, entry.name);
|
||||
return (
|
||||
fs.existsSync(path.join(pluginDir, "package.json")) ||
|
||||
fs.existsSync(path.join(pluginDir, "openclaw.plugin.json"))
|
||||
);
|
||||
});
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isSourceCheckoutExtensionsDir(extensionsDir: string): boolean {
|
||||
const packageRoot = path.dirname(extensionsDir);
|
||||
return (
|
||||
fs.existsSync(path.join(packageRoot, ".git")) &&
|
||||
fs.existsSync(path.join(packageRoot, "pnpm-workspace.yaml")) &&
|
||||
fs.existsSync(path.join(packageRoot, "src")) &&
|
||||
fs.existsSync(extensionsDir) &&
|
||||
hasDiscoverablePluginTree(extensionsDir)
|
||||
);
|
||||
}
|
||||
|
||||
function resolveBundledSourceCheckoutExtensionsDir(bundledRoot?: string): string | undefined {
|
||||
if (!bundledRoot) {
|
||||
return undefined;
|
||||
}
|
||||
const legacyRoot = buildLegacyBundledRootPath(bundledRoot);
|
||||
if (!legacyRoot || !isSourceCheckoutExtensionsDir(legacyRoot)) {
|
||||
return undefined;
|
||||
}
|
||||
return legacyRoot;
|
||||
}
|
||||
|
||||
function readChildDirectoryNames(dir: string | undefined): Set<string> {
|
||||
if (!dir || !fs.existsSync(dir)) {
|
||||
return new Set();
|
||||
}
|
||||
try {
|
||||
return new Set(
|
||||
fs
|
||||
.readdirSync(dir, { withFileTypes: true })
|
||||
.filter((entry) => entry.isDirectory())
|
||||
.map((entry) => entry.name),
|
||||
);
|
||||
} catch {
|
||||
return new Set();
|
||||
}
|
||||
}
|
||||
|
||||
function discoverFromPath(params: {
|
||||
rawPath: string;
|
||||
origin: PluginOrigin;
|
||||
@@ -996,6 +1049,24 @@ export function discoverOpenClawPlugins(params: {
|
||||
realpathCache,
|
||||
});
|
||||
}
|
||||
const sourceCheckoutExtensionsDir = resolveBundledSourceCheckoutExtensionsDir(roots.stock);
|
||||
const sourceCheckoutMatchesBundledRoot = resolvesToSameDirectory(
|
||||
sourceCheckoutExtensionsDir,
|
||||
roots.stock,
|
||||
realpathCache,
|
||||
);
|
||||
if (sourceCheckoutExtensionsDir && !sourceCheckoutMatchesBundledRoot) {
|
||||
discoverInDirectory({
|
||||
dir: sourceCheckoutExtensionsDir,
|
||||
origin: "bundled",
|
||||
ownershipUid: params.ownershipUid,
|
||||
candidates: result.candidates,
|
||||
diagnostics: result.diagnostics,
|
||||
seen,
|
||||
realpathCache,
|
||||
skipDirectories: readChildDirectoryNames(roots.stock),
|
||||
});
|
||||
}
|
||||
for (const installedPath of collectInstalledPluginRecordPaths(params.installRecords, env)) {
|
||||
discoverFromPath({
|
||||
rawPath: installedPath,
|
||||
|
||||
Reference in New Issue
Block a user