UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

376 lines (375 loc) 18.7 kB
import { c as normalizeOptionalString } from "./string-coerce-mnp54Vah.js"; import { o as isRecord } from "./record-coerce-DHZ4bFlT.js"; import { a as normalizeOptionalTrimmedStringList } from "./string-normalization-WNUDCpXX.js"; import { f as safeRealpathSync, i as isPathInside } from "./path-BlG8lhgR.js"; import { i as tracePluginLifecyclePhase, r as normalizePluginDependencySpecs } from "./discovery-BDSfxwT6.js"; import { p as tryReadJsonSync } from "./json-files-2umMHm0W.js"; import { r as getPackageManifestMetadata, t as DEFAULT_PLUGIN_ENTRY_CANDIDATES } from "./manifest-BcY4wyAU.js"; import { t as loadPluginManifestRegistry } from "./manifest-registry-BywZIeAq.js"; import "./path-safety-4zNHq1Ot.js"; import { n as registerPluginMetadataProcessMemoLifecycleClear } from "./plugin-metadata-lifecycle-C3dWg4tn.js"; import { f as extractPluginInstallRecordsFromInstalledPluginIndex, g as hashJson } from "./installed-plugin-index-BSYm7o5l.js"; import fs from "node:fs"; import path from "node:path"; //#region src/plugins/manifest-registry-installed.ts /** Builds manifest registry records from installed plugin index snapshots. */ const installedManifestRegistryIndexFingerprintCache = /* @__PURE__ */ new WeakMap(); const installedPackageJsonPathCache = /* @__PURE__ */ new Map(); const installedPackageMetadataCache = /* @__PURE__ */ new Map(); const MAX_INSTALLED_PACKAGE_JSON_PATH_CACHE_ENTRIES = 256; const MAX_INSTALLED_PACKAGE_METADATA_CACHE_ENTRIES = 256; function clearInstalledManifestRegistryProcessCaches() { installedPackageJsonPathCache.clear(); installedPackageMetadataCache.clear(); } registerPluginMetadataProcessMemoLifecycleClear(clearInstalledManifestRegistryProcessCaches); function isDeepFrozenJsonLike(value, seen = /* @__PURE__ */ new WeakSet()) { if (!value || typeof value !== "object") return true; const object = value; if (seen.has(object)) return true; if (!Object.isFrozen(object)) return false; seen.add(object); return Object.values(value).every((entry) => isDeepFrozenJsonLike(entry, seen)); } function hasPersistedFileSignatures(index) { return index.plugins.every((record) => record.manifestFile !== void 0 && (record.packageJson === void 0 || record.packageJson.fileSignature !== void 0)); } function isInstalledManifestRegistryIndexFingerprintCacheable(index) { return hasPersistedFileSignatures(index) && isDeepFrozenJsonLike(index); } function isRelativePathInsideOrEqual(relativePath) { return relativePath === "" || relativePath !== ".." && !relativePath.startsWith(`..${path.sep}`) && !path.isAbsolute(relativePath); } function resolvePackageJsonPath(record, realpathCache) { if (!record.packageJson?.path) return; const cacheKey = buildInstalledPackageJsonPathCacheKey(record); if (cacheKey) { const cached = installedPackageJsonPathCache.get(cacheKey); if (cached !== void 0) return cached ?? void 0; } const rootDir = resolveInstalledPluginRootDir(record); const realRootDir = safeRealpathSync(rootDir, realpathCache) ?? path.resolve(rootDir); const packageJsonPath = path.resolve(realRootDir, record.packageJson.path); if (!isRelativePathInsideOrEqual(path.relative(realRootDir, packageJsonPath))) return rememberInstalledPackageJsonPath(cacheKey, void 0); const packageJsonRealPath = safeRealpathSync(packageJsonPath, realpathCache); if (!packageJsonRealPath || !isPathInside(realRootDir, packageJsonRealPath)) return rememberInstalledPackageJsonPath(cacheKey, void 0); return rememberInstalledPackageJsonPath(cacheKey, packageJsonPath); } function safeFileSignature(filePath) { if (!filePath) return; try { return formatFileSignature(filePath, fs.statSync(filePath)); } catch { return `${filePath}:missing`; } } function formatFileSignature(filePath, signature) { return `${filePath}:${signature.size}:${signature.mtimeMs}`; } function rememberInstalledPackageMetadata(key, metadata) { if (!key) return metadata; installedPackageMetadataCache.set(key, metadata); while (installedPackageMetadataCache.size > MAX_INSTALLED_PACKAGE_METADATA_CACHE_ENTRIES) { const oldest = installedPackageMetadataCache.keys().next().value; if (oldest === void 0) break; installedPackageMetadataCache.delete(oldest); } return metadata; } function rememberInstalledPackageJsonPath(key, packageJsonPath) { if (!key) return packageJsonPath; installedPackageJsonPathCache.set(key, packageJsonPath ?? null); while (installedPackageJsonPathCache.size > MAX_INSTALLED_PACKAGE_JSON_PATH_CACHE_ENTRIES) { const oldest = installedPackageJsonPathCache.keys().next().value; if (oldest === void 0) break; installedPackageJsonPathCache.delete(oldest); } return packageJsonPath; } function buildInstalledPackageJsonPathCacheKey(record) { if (!record.packageJson?.path || !record.packageJson.hash) return; return hashJson({ rootDir: path.resolve(resolveInstalledPluginRootDir(record)), packageJson: record.packageJson }); } function buildInstalledPackageMetadataCacheKey(params) { if (!params.packageJsonPath || !params.record.packageJson?.hash) return; return hashJson({ packageJsonPath: path.resolve(params.packageJsonPath), packageJson: params.record.packageJson, packageChannel: params.record.packageChannel ?? null }); } function buildInstalledManifestRegistryIndexKey(index) { const realpathCache = /* @__PURE__ */ new Map(); return { version: index.version, hostContractVersion: index.hostContractVersion, compatRegistryVersion: index.compatRegistryVersion, migrationVersion: index.migrationVersion, policyHash: index.policyHash, installRecords: index.installRecords, diagnostics: index.diagnostics, plugins: index.plugins.map((record) => { const packageJsonPath = resolvePackageJsonPath(record, realpathCache); const packageJsonFile = record.packageJson?.fileSignature ? packageJsonPath ? formatFileSignature(packageJsonPath, record.packageJson.fileSignature) : void 0 : safeFileSignature(packageJsonPath); return { pluginId: record.pluginId, packageName: record.packageName, packageVersion: record.packageVersion, installRecord: record.installRecord, installRecordHash: record.installRecordHash, packageInstall: record.packageInstall, packageChannel: record.packageChannel, manifestPath: record.manifestPath, manifestHash: record.manifestHash, manifestFile: record.manifestFile ? formatFileSignature(record.manifestPath, record.manifestFile) : safeFileSignature(record.manifestPath), format: record.format, bundleFormat: record.bundleFormat, source: record.source, setupSource: record.setupSource, packageJson: record.packageJson, packageJsonFile, rootDir: record.rootDir, origin: record.origin, enabled: record.enabled, enabledByDefault: record.enabledByDefault, enabledByDefaultOnPlatforms: record.enabledByDefaultOnPlatforms ? [...record.enabledByDefaultOnPlatforms] : void 0, syntheticAuthRefs: record.syntheticAuthRefs, startup: record.startup, compat: record.compat }; }) }; } function resolveInstalledManifestRegistryIndexFingerprint(index) { const cached = installedManifestRegistryIndexFingerprintCache.get(index); if (cached) return cached; const fingerprint = hashJson(buildInstalledManifestRegistryIndexKey(index)); if (isInstalledManifestRegistryIndexFingerprintCacheable(index)) installedManifestRegistryIndexFingerprintCache.set(index, fingerprint); return fingerprint; } function resolveInstalledPluginRootDir(record) { return record.rootDir || path.dirname(record.manifestPath || process.cwd()); } function resolveFallbackPluginSource(record) { const rootDir = resolveInstalledPluginRootDir(record); for (const entry of DEFAULT_PLUGIN_ENTRY_CANDIDATES) { const candidate = path.join(rootDir, entry); if (fs.existsSync(candidate)) return candidate; } return path.join(rootDir, DEFAULT_PLUGIN_ENTRY_CANDIDATES[0]); } function normalizePackageChannelCommands(commands) { if (!isRecord(commands)) return; const nativeCommandsAutoEnabled = typeof commands.nativeCommandsAutoEnabled === "boolean" ? commands.nativeCommandsAutoEnabled : void 0; const nativeSkillsAutoEnabled = typeof commands.nativeSkillsAutoEnabled === "boolean" ? commands.nativeSkillsAutoEnabled : void 0; return nativeCommandsAutoEnabled !== void 0 || nativeSkillsAutoEnabled !== void 0 ? { ...nativeCommandsAutoEnabled !== void 0 ? { nativeCommandsAutoEnabled } : {}, ...nativeSkillsAutoEnabled !== void 0 ? { nativeSkillsAutoEnabled } : {} } : void 0; } function normalizePackageChannelExposure(exposure) { if (!isRecord(exposure)) return; const configured = typeof exposure.configured === "boolean" ? exposure.configured : void 0; const setup = typeof exposure.setup === "boolean" ? exposure.setup : void 0; const docs = typeof exposure.docs === "boolean" ? exposure.docs : void 0; return configured !== void 0 || setup !== void 0 || docs !== void 0 ? { ...configured !== void 0 ? { configured } : {}, ...setup !== void 0 ? { setup } : {}, ...docs !== void 0 ? { docs } : {} } : void 0; } function normalizePackageChannelConfiguredState(configuredState) { if (!isRecord(configuredState)) return; const env = isRecord(configuredState.env) ? { ...normalizeOptionalTrimmedStringList(configuredState.env.allOf)?.length ? { allOf: normalizeOptionalTrimmedStringList(configuredState.env.allOf) } : {}, ...normalizeOptionalTrimmedStringList(configuredState.env.anyOf)?.length ? { anyOf: normalizeOptionalTrimmedStringList(configuredState.env.anyOf) } : {} } : void 0; const specifier = normalizeOptionalString(configuredState.specifier); const exportName = normalizeOptionalString(configuredState.exportName); return specifier || exportName || env && Object.keys(env).length > 0 ? { ...specifier ? { specifier } : {}, ...exportName ? { exportName } : {}, ...env && Object.keys(env).length > 0 ? { env } : {} } : void 0; } function normalizePackageChannelPersistedAuthState(persistedAuthState) { if (!isRecord(persistedAuthState)) return; const specifier = normalizeOptionalString(persistedAuthState.specifier); const exportName = normalizeOptionalString(persistedAuthState.exportName); return specifier || exportName ? { ...specifier ? { specifier } : {}, ...exportName ? { exportName } : {} } : void 0; } function normalizePackageChannelDoctorCapabilities(doctorCapabilities) { if (!isRecord(doctorCapabilities)) return; const dmAllowFromMode = doctorCapabilities.dmAllowFromMode === "topOnly" || doctorCapabilities.dmAllowFromMode === "topOrNested" || doctorCapabilities.dmAllowFromMode === "nestedOnly" ? doctorCapabilities.dmAllowFromMode : void 0; const groupModel = doctorCapabilities.groupModel === "sender" || doctorCapabilities.groupModel === "route" || doctorCapabilities.groupModel === "hybrid" ? doctorCapabilities.groupModel : void 0; const groupAllowFromFallbackToAllowFrom = typeof doctorCapabilities.groupAllowFromFallbackToAllowFrom === "boolean" ? doctorCapabilities.groupAllowFromFallbackToAllowFrom : void 0; const warnOnEmptyGroupSenderAllowlist = typeof doctorCapabilities.warnOnEmptyGroupSenderAllowlist === "boolean" ? doctorCapabilities.warnOnEmptyGroupSenderAllowlist : void 0; return dmAllowFromMode || groupModel || groupAllowFromFallbackToAllowFrom !== void 0 || warnOnEmptyGroupSenderAllowlist !== void 0 ? { ...dmAllowFromMode ? { dmAllowFromMode } : {}, ...groupModel ? { groupModel } : {}, ...groupAllowFromFallbackToAllowFrom !== void 0 ? { groupAllowFromFallbackToAllowFrom } : {}, ...warnOnEmptyGroupSenderAllowlist !== void 0 ? { warnOnEmptyGroupSenderAllowlist } : {} } : void 0; } function normalizePackageChannelCliOptions(cliAddOptions) { if (!Array.isArray(cliAddOptions)) return; const normalized = cliAddOptions.flatMap((option) => { if (!isRecord(option)) return []; const flags = normalizeOptionalString(option.flags); const description = normalizeOptionalString(option.description); if (!flags || !description) return []; const defaultValue = typeof option.defaultValue === "boolean" || typeof option.defaultValue === "string" ? option.defaultValue : void 0; return [{ flags, description, ...defaultValue !== void 0 ? { defaultValue } : {} }]; }); return normalized.length > 0 ? normalized : void 0; } function normalizePersistedPackageChannel(value) { if (!isRecord(value)) return; const id = normalizeOptionalString(value.id); if (!id) return; const channel = { id }; for (const key of [ "label", "selectionLabel", "detailLabel", "docsPath", "docsLabel", "blurb", "systemImage", "selectionDocsPrefix" ]) { const normalized = normalizeOptionalString(value[key]); if (normalized) channel[key] = normalized; } if (typeof value.order === "number" && Number.isFinite(value.order)) channel.order = value.order; for (const key of [ "aliases", "preferOver", "selectionExtras" ]) { const normalized = normalizeOptionalTrimmedStringList(value[key]); if (normalized?.length) channel[key] = normalized; } for (const key of [ "selectionDocsOmitLabel", "markdownCapable", "showConfigured", "showInSetup", "quickstartAllowFrom", "forceAccountBinding", "preferSessionLookupForAnnounceTarget" ]) if (typeof value[key] === "boolean") channel[key] = value[key]; const exposure = normalizePackageChannelExposure(value.exposure); if (exposure) channel.exposure = exposure; const commands = normalizePackageChannelCommands(value.commands); if (commands) channel.commands = commands; const configuredState = normalizePackageChannelConfiguredState(value.configuredState); if (configuredState) channel.configuredState = configuredState; const persistedAuthState = normalizePackageChannelPersistedAuthState(value.persistedAuthState); if (persistedAuthState) channel.persistedAuthState = persistedAuthState; const doctorCapabilities = normalizePackageChannelDoctorCapabilities(value.doctorCapabilities); if (doctorCapabilities) channel.doctorCapabilities = doctorCapabilities; const cliAddOptions = normalizePackageChannelCliOptions(value.cliAddOptions); if (cliAddOptions) channel.cliAddOptions = cliAddOptions; return channel; } function resolveInstalledPackageMetadata(record, realpathCache) { const recordPackageChannel = normalizePersistedPackageChannel(record.packageChannel); const fallbackPackageManifest = recordPackageChannel ? { channel: recordPackageChannel } : void 0; const packageJsonPath = record.packageJson?.path ? resolvePackageJsonPath(record, realpathCache) : void 0; const cacheKey = buildInstalledPackageMetadataCacheKey({ packageJsonPath, record }); const cached = cacheKey ? installedPackageMetadataCache.get(cacheKey) : void 0; if (cached) return cached; if (!packageJsonPath) return rememberInstalledPackageMetadata(cacheKey, fallbackPackageManifest ? { packageManifest: fallbackPackageManifest } : {}); const packageJson = tryReadJsonSync(packageJsonPath); if (packageJson) { const packageManifest = getPackageManifestMetadata(packageJson); const dependencies = normalizePluginDependencySpecs({ dependencies: packageJson.dependencies, optionalDependencies: packageJson.optionalDependencies }); if (!packageManifest) return rememberInstalledPackageMetadata(cacheKey, { ...fallbackPackageManifest ? { packageManifest: fallbackPackageManifest } : {}, packageDependencies: dependencies.dependencies, packageOptionalDependencies: dependencies.optionalDependencies }); const packageChannel = normalizePersistedPackageChannel(packageManifest.channel); const channel = recordPackageChannel || packageChannel ? { ...recordPackageChannel, ...packageChannel } : void 0; const { channel: _ignoredChannel, ...packageManifestWithoutChannel } = packageManifest; return rememberInstalledPackageMetadata(cacheKey, { packageManifest: { ...packageManifestWithoutChannel, ...channel ? { channel } : {} }, packageDependencies: dependencies.dependencies, packageOptionalDependencies: dependencies.optionalDependencies }); } return rememberInstalledPackageMetadata(cacheKey, fallbackPackageManifest ? { packageManifest: fallbackPackageManifest } : {}); } function toPluginCandidate(record, realpathCache) { const rootDir = resolveInstalledPluginRootDir(record); const packageMetadata = resolveInstalledPackageMetadata(record, realpathCache); return { idHint: record.pluginId, source: record.source ?? resolveFallbackPluginSource(record), ...record.setupSource ? { setupSource: record.setupSource } : {}, rootDir, origin: record.origin, ...record.format ? { format: record.format } : {}, ...record.bundleFormat ? { bundleFormat: record.bundleFormat } : {}, ...record.packageName ? { packageName: record.packageName } : {}, ...record.packageVersion ? { packageVersion: record.packageVersion } : {}, ...packageMetadata.packageManifest ? { packageManifest: packageMetadata.packageManifest } : {}, ...packageMetadata.packageDependencies ? { packageDependencies: packageMetadata.packageDependencies } : {}, ...packageMetadata.packageOptionalDependencies ? { packageOptionalDependencies: packageMetadata.packageOptionalDependencies } : {}, packageDir: rootDir }; } function loadPluginManifestRegistryForInstalledIndex(params) { return tracePluginLifecyclePhase("manifest registry", () => { if (params.pluginIds && params.pluginIds.length === 0) return { plugins: [], diagnostics: [] }; const env = params.env ?? process.env; const pluginIdSet = params.pluginIds?.length ? new Set(params.pluginIds) : null; const realpathCache = /* @__PURE__ */ new Map(); const diagnostics = pluginIdSet ? params.index.diagnostics.filter((diagnostic) => { const pluginId = diagnostic.pluginId; return !pluginId || pluginIdSet.has(pluginId); }) : params.index.diagnostics; const candidates = params.index.plugins.filter((plugin) => params.includeDisabled || plugin.enabled).filter((plugin) => !pluginIdSet || pluginIdSet.has(plugin.pluginId)).map((plugin) => toPluginCandidate(plugin, realpathCache)); return loadPluginManifestRegistry({ config: params.config, workspaceDir: params.workspaceDir, env, candidates, diagnostics: [...diagnostics], installRecords: extractPluginInstallRecordsFromInstalledPluginIndex(params.index), ...params.bundledChannelConfigCollector ? { bundledChannelConfigCollector: params.bundledChannelConfigCollector } : {} }); }, { includeDisabled: params.includeDisabled === true, pluginIdCount: params.pluginIds?.length, indexPluginCount: params.index.plugins.length }); } //#endregion export { resolveInstalledManifestRegistryIndexFingerprint as n, loadPluginManifestRegistryForInstalledIndex as t };