openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
120 lines (119 loc) • 6.15 kB
JavaScript
import { c as resolveUserPath } from "./home-dir-BPhrG-aM.js";
import { o as safeRealpathSync } from "./path-safety-Bi0ppMWC.js";
import { r as isPathInside } from "./path-guards-Cp-mGr3-.js";
import "./utils-P__uGsPB.js";
import "./path-safety-BT3PFs5V.js";
import { r as resolveInstalledPluginIndexInstallOwner, t as isInstalledPluginIndexInstallOwnerAmbiguous } from "./installed-plugin-index-install-owner-Bd-Byre8.js";
import path from "node:path";
//#region src/plugins/installed-plugin-package-ownership.ts
function collectDuplicateInstallRecordOwners(index, env, realpathCache) {
const ownersByPath = /* @__PURE__ */ new Map();
const duplicateOwners = /* @__PURE__ */ new Set();
for (const [installOwner, record] of Object.entries(index.installRecords)) {
const rawPath = record.installPath?.trim() || record.sourcePath?.trim();
if (!rawPath) continue;
const resolved = path.resolve(resolveUserPath(rawPath, env));
const pathKey = safeRealpathSync(resolved, realpathCache) ?? resolved;
const existingOwner = ownersByPath.get(pathKey);
if (existingOwner && existingOwner !== installOwner) {
duplicateOwners.add(existingOwner);
duplicateOwners.add(installOwner);
}
ownersByPath.set(pathKey, installOwner);
}
return duplicateOwners;
}
function ownershipError(pluginId, detail) {
return {
ok: false,
error: `Plugin "${pluginId}" ${detail}. Refresh the plugin registry, then reinstall the package or run openclaw doctor before retrying.`
};
}
function createInstalledPluginOwnershipResolver(index, env = process.env) {
const targets = /* @__PURE__ */ new Map();
const childrenByOwner = /* @__PURE__ */ new Map();
for (const entry of index.plugins) {
if (!targets.has(entry.pluginId)) targets.set(entry.pluginId, entry);
const installOwner = resolveInstalledPluginIndexInstallOwner(entry);
if (installOwner) {
const children = childrenByOwner.get(installOwner) ?? [];
children.push(entry.pluginId);
childrenByOwner.set(installOwner, children);
}
}
for (const children of childrenByOwner.values()) children.sort();
const realpathCache = /* @__PURE__ */ new Map();
let duplicateOwners;
const duplicates = () => duplicateOwners ??= collectDuplicateInstallRecordOwners(index, env, realpathCache);
const unsafeOwners = /* @__PURE__ */ new Map();
function resolvePackage(pluginId) {
const target = targets.get(pluginId);
if (target && isInstalledPluginIndexInstallOwnerAmbiguous(target)) return ownershipError(pluginId, "has ambiguous package ownership");
const ownerFromTarget = target ? resolveInstalledPluginIndexInstallOwner(target) : void 0;
if (target && !ownerFromTarget) return ownershipError(pluginId, "has no authoritative package-owner metadata");
const ownerFromRecord = Object.hasOwn(index.installRecords, pluginId) ? pluginId : void 0;
const installOwner = ownerFromTarget ?? ownerFromRecord;
if (!installOwner) return ownershipError(pluginId, "is not associated with a tracked package install");
if (ownerFromTarget && ownerFromRecord && ownerFromTarget !== ownerFromRecord) return ownershipError(pluginId, "matches conflicting package owners");
const installRecord = index.installRecords[installOwner];
if (!installRecord) return ownershipError(pluginId, `references missing package owner "${installOwner}"`);
if (duplicates().has(installOwner)) return ownershipError(pluginId, `shares package path ownership with "${installOwner}"`);
const [firstPluginId, ...remainingPluginIds] = childrenByOwner.get(installOwner) ?? [];
if (!firstPluginId) return ownershipError(pluginId, `package owner "${installOwner}" has no authoritative runtime child list`);
const pluginIds = [firstPluginId, ...remainingPluginIds];
const hasUnsafePackageEntry = unsafeOwners.get(installOwner) ?? index.plugins.some((entry) => installRecordPathMatchesPluginRoot(installRecord, entry.rootDir, env, realpathCache) && resolveInstalledPluginIndexInstallOwner(entry) !== installOwner);
unsafeOwners.set(installOwner, hasUnsafePackageEntry);
if (hasUnsafePackageEntry) return ownershipError(pluginId, `package owner "${installOwner}" has conflicting child rows`);
return {
ok: true,
value: {
installOwner,
installRecord,
pluginIds
}
};
}
function resolveLifecycle(pluginId) {
const ownership = resolvePackage(pluginId);
if (ownership.ok) return {
ok: true,
value: {
kind: "package",
...ownership.value
}
};
const installRecord = index.installRecords[pluginId];
if (!Object.hasOwn(index.installRecords, pluginId) || !installRecord || duplicates().has(pluginId)) return ownership;
if (index.plugins.some((entry) => entry.pluginId === pluginId || installRecordPathMatchesPluginRoot(installRecord, entry.rootDir, env, realpathCache))) return ownership;
return {
ok: true,
value: {
kind: "orphan",
installOwner: pluginId,
installRecord,
pluginIds: []
}
};
}
return {
resolvePackage,
resolveLifecycle
};
}
function installRecordPathMatchesPluginRoot(record, rootDir, env, realpathCache) {
const resolvedRoot = safeRealpathSync(path.resolve(rootDir), realpathCache) ?? path.resolve(rootDir);
return [record.installPath, record.sourcePath].some((candidate) => {
if (!candidate?.trim()) return false;
const candidatePath = path.resolve(resolveUserPath(candidate, env));
const resolvedCandidate = safeRealpathSync(candidatePath, realpathCache) ?? candidatePath;
return isPathInside(resolvedCandidate, resolvedRoot);
});
}
function hasMissingInstalledPluginOwnerMetadata(index, env = process.env) {
const realpathCache = /* @__PURE__ */ new Map();
if (collectDuplicateInstallRecordOwners(index, env, realpathCache).size > 0) return true;
const installRecords = Object.entries(index.installRecords);
return index.plugins.some((plugin) => isInstalledPluginIndexInstallOwnerAmbiguous(plugin) || !resolveInstalledPluginIndexInstallOwner(plugin) && installRecords.some(([, record]) => installRecordPathMatchesPluginRoot(record, plugin.rootDir, env, realpathCache)));
}
//#endregion
export { hasMissingInstalledPluginOwnerMetadata as n, createInstalledPluginOwnershipResolver as t };