UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

250 lines (249 loc) • 10.3 kB
import { o as resolveUserPath } from "./home-dir-Dc6nN6HB.mjs"; import { c as isRecord } from "./record-coerce-TIsquoVR.mjs"; import { _ as redactSensitiveText } from "./redact-DJ8j6ADa.mjs"; import "./utils-DgZn2dLu.mjs"; import { Fn as object, Jn as string, Lt as boolean, Nt as array, Pn as number, or as union, qn as strictObject, xn as literal } from "./schemas-BOYIvvln.mjs"; import { n as isPathInside } from "./path-safety-6KJ2Rbnw.mjs"; import { l as pluginCacheRealpathSync } from "./package-manifest-CEbdS_C4.mjs"; import { D as resolvePluginCandidateInstallOwner, T as isPluginCandidateInstallOwnerAmbiguous } from "./discovery-Dma3bVNk.mjs"; import { r as isTrustedOfficialPluginInstallRecord } from "./official-external-install-records-BVI7ulqm.mjs"; import { Buffer } from "node:buffer"; //#region src/config/zod-schema.installs.ts const InstallSourceSchema = union([ literal("npm"), literal("archive"), literal("path"), literal("clawhub"), literal("git") ]); const PluginInstallSourceSchema = union([InstallSourceSchema, literal("marketplace")]); /** Zod object shape for persisted generic install records. */ const InstallRecordShape = { source: InstallSourceSchema, spec: string().optional(), sourcePath: string().optional(), installPath: string().optional(), version: string().optional(), resolvedName: string().optional(), resolvedVersion: string().optional(), resolvedSpec: string().optional(), integrity: string().optional(), shasum: string().optional(), resolvedAt: string().optional(), installedAt: string().optional(), clawhubUrl: string().optional(), clawhubPackage: string().optional(), clawhubFamily: union([literal("code-plugin"), literal("bundle-plugin")]).optional(), clawhubChannel: union([ literal("official"), literal("community"), literal("private") ]).optional(), clawhubTrustDisposition: union([ literal("clean"), literal("review-recommended"), literal("review-required"), literal("blocked") ]).optional(), clawhubTrustScanStatus: string().optional(), clawhubTrustModerationState: string().optional(), clawhubTrustReasons: array(string()).optional(), clawhubTrustPending: boolean().optional(), clawhubTrustStale: boolean().optional(), clawhubTrustCheckedAt: string().optional(), clawhubTrustAcknowledgedAt: string().optional(), artifactKind: union([literal("legacy-zip"), literal("npm-pack")]).optional(), artifactFormat: union([literal("zip"), literal("tgz")]).optional(), npmIntegrity: string().optional(), npmShasum: string().optional(), npmTarballName: string().optional(), clawpackSha256: string().optional(), clawpackSpecVersion: number().int().nonnegative().optional(), clawpackManifestSha256: string().optional(), clawpackSize: number().int().nonnegative().optional(), gitUrl: string().optional(), gitRef: string().optional(), gitCommit: string().optional() }; object(InstallRecordShape); const PluginInstallRecordShape = { ...InstallRecordShape, source: PluginInstallSourceSchema, marketplaceName: string().optional(), marketplaceSource: string().optional(), marketplacePlugin: string().optional(), acceptedSurface: strictObject({ channels: array(string().min(1)), providers: array(string().min(1)), tools: array(string().min(1)), contracts: array(string().min(1)), hooks: array(string().min(1)), mcpServers: array(string().min(1)), cliCommands: array(string().min(1)), cliBackends: array(string().min(1)), skills: array(string().min(1)), dangerousConfigFlags: array(string().min(1)) }).optional(), acceptedSurfaceHash: string().optional(), acceptedSurfaceAt: string().optional(), acceptedSurfaceIntegrity: string().optional() }; //#endregion //#region src/config/plugin-install-record-map.ts const PluginInstallRecordSchema = object(PluginInstallRecordShape).passthrough(); const NORMALIZED_STRING_FIELDS = [ "spec", "sourcePath", "installPath", "version", "resolvedName", "resolvedVersion", "resolvedSpec", "integrity", "shasum", "resolvedAt", "installedAt", "clawhubUrl", "clawhubPackage", "clawhubTrustScanStatus", "clawhubTrustModerationState", "clawhubTrustCheckedAt", "clawhubTrustAcknowledgedAt", "npmIntegrity", "npmShasum", "npmTarballName", "clawpackSha256", "clawpackManifestSha256", "gitUrl", "gitRef", "gitCommit", "marketplaceName", "marketplaceSource", "marketplacePlugin", "acceptedSurfaceHash", "acceptedSurfaceAt", "acceptedSurfaceIntegrity" ]; function createPluginInstallRecordMap() { return Object.create(null); } function setPluginInstallRecordMapEntry(records, pluginId, record) { Object.defineProperty(records, pluginId, { configurable: true, enumerable: true, value: record, writable: true }); } function getPluginInstallRecordMapEntry(records, pluginId) { return records && Object.hasOwn(records, pluginId) ? records[pluginId] : void 0; } function copyPluginInstallRecordMap(records) { const copied = createPluginInstallRecordMap(); for (const [pluginId, record] of Object.entries(records ?? {})) setPluginInstallRecordMapEntry(copied, pluginId, record); return copied; } function parsePluginInstallRecord(value) { const parsed = PluginInstallRecordSchema.safeParse(value); if (!parsed.success) return null; const record = parsed.data; for (const field of NORMALIZED_STRING_FIELDS) { const fieldValue = record[field]; if (fieldValue === void 0) continue; const normalized = fieldValue.trim(); if (normalized) record[field] = normalized; else delete record[field]; } if (record.clawhubTrustReasons) { const reasons = record.clawhubTrustReasons.map((entry) => entry.trim()).filter(Boolean); if (reasons.length > 0) record.clawhubTrustReasons = reasons; else delete record.clawhubTrustReasons; } return record; } function parsePluginInstallRecordMap(value) { if (!isRecord(value)) return null; const records = createPluginInstallRecordMap(); for (const [pluginId, rawRecord] of Object.entries(value)) { const record = parsePluginInstallRecord(rawRecord); if (!record) return null; setPluginInstallRecordMapEntry(records, pluginId, record); } return records; } function inspectPluginInstallRecordMap(value) { if (value === void 0) return { status: "missing" }; const records = parsePluginInstallRecordMap(value); return records ? { status: "valid", records } : { status: "invalid" }; } /** * Object enumeration reorders integer-index keys, so persisted bytes must be * assembled from sorted entries instead of relying on object insertion order. */ function serializePluginInstallRecordMap(records) { return `{${Object.entries(records).toSorted(([left], [right]) => Buffer.compare(Buffer.from(left), Buffer.from(right))).map(([pluginId, record]) => `${JSON.stringify(pluginId)}:${JSON.stringify(record)}`).join(",")}}`; } //#endregion //#region src/plugins/installed-plugin-record-match.ts function resolveCandidateInstallOwner(params) { if (isPluginCandidateInstallOwnerAmbiguous(params.candidate)) return; const installOwner = resolvePluginCandidateInstallOwner(params.candidate); if (installOwner) return Object.hasOwn(params.installRecords, installOwner) ? installOwner : void 0; } function matchesInstalledPluginRecord(params) { if (params.candidate.origin !== "global" && params.candidate.origin !== "config") return false; const installOwner = resolveCandidateInstallOwner(params); const record = installOwner ? params.installRecords[installOwner] : void 0; if (!record) return false; const candidatePaths = [ params.candidate.rootDir, params.candidate.packageDir, params.candidate.source, params.candidate.setupSource ].filter((entry) => typeof entry === "string" && entry.trim().length > 0).map((entry) => { const resolved = resolveUserPath(entry, params.env); return pluginCacheRealpathSync(resolved) ?? resolved; }); const trackedPaths = (params.installPathOnly ? [record.installPath] : [record.installPath, record.sourcePath]).filter((entry) => typeof entry === "string" && entry.trim().length > 0).map((entry) => { const resolved = resolveUserPath(entry, params.env); return pluginCacheRealpathSync(resolved) ?? resolved; }); if (candidatePaths.length === 0 || trackedPaths.length === 0) return false; return trackedPaths.some((trackedPath) => candidatePaths.some((candidatePath) => candidatePath === trackedPath || isPathInside(trackedPath, candidatePath) || isPathInside(candidatePath, trackedPath))); } function resolvePluginTrust(params) { const installOwner = resolveCandidateInstallOwner(params); const record = installOwner ? params.installRecords[installOwner] : void 0; const origin = params.candidate.origin; let reason; if (origin === "bundled") reason = "bundled"; else if (isPluginCandidateInstallOwnerAmbiguous(params.candidate)) reason = "owner-ambiguous"; else if (origin === "workspace" || record?.source === "path" || record?.source === "npm" && (record.artifactKind !== void 0 || record.sourcePath !== void 0)) reason = "origin-path"; else if (!record || !installOwner) reason = "record-missing"; else if (!matchesInstalledPluginRecord({ pluginId: params.pluginId, candidate: params.candidate, env: params.env, installRecords: params.installRecords, installPathOnly: true })) reason = "install-path-mismatch"; else if (isTrustedOfficialPluginInstallRecord({ pluginId: installOwner, packageName: params.candidate.packageName, record })) reason = "trusted-official"; else if (record.source === "npm" && record.spec === void 0 && record.resolvedName === void 0 && record.resolvedSpec === void 0 || record.source === "clawhub" && record.clawhubUrl === void 0 && record.clawhubChannel === void 0) reason = "provenance-missing"; else reason = "provenance-invalid"; return { reason, registryPath: params.registryPath, origin, installSource: record?.source, installSpec: record?.spec === void 0 ? void 0 : redactSensitiveText(record.spec, { mode: "tools" }) }; } //#endregion export { getPluginInstallRecordMapEntry as a, parsePluginInstallRecordMap as c, createPluginInstallRecordMap as i, serializePluginInstallRecordMap as l, resolvePluginTrust as n, inspectPluginInstallRecordMap as o, copyPluginInstallRecordMap as r, parsePluginInstallRecord as s, matchesInstalledPluginRecord as t, setPluginInstallRecordMapEntry as u };