UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

120 lines (119 loc) 6.15 kB
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 };