




















@@ -21,12 +21,27 @@ import {
2121} from "./manifest.js";
2222import { isPathInside, safeRealpathSync } from "./path-safety.js";
2323import { tracePluginLifecyclePhase } from "./plugin-lifecycle-trace.js";
24+import { registerPluginMetadataProcessMemoLifecycleClear } from "./plugin-metadata-lifecycle.js";
2425import {
2526normalizePluginDependencySpecs,
2627type PluginDependencySpecMap,
2728} from "./status-dependencies.js";
28292930const installedManifestRegistryIndexFingerprintCache = new WeakMap<InstalledPluginIndex, string>();
31+const installedPackageMetadataCache = new Map<string, InstalledPackageMetadata>();
32+const MAX_INSTALLED_PACKAGE_METADATA_CACHE_ENTRIES = 256;
33+34+type InstalledPackageMetadata = {
35+packageManifest?: OpenClawPackageManifest;
36+packageDependencies?: PluginDependencySpecMap;
37+packageOptionalDependencies?: PluginDependencySpecMap;
38+};
39+40+export function clearInstalledManifestRegistryProcessCaches(): void {
41+installedPackageMetadataCache.clear();
42+}
43+44+registerPluginMetadataProcessMemoLifecycleClear(clearInstalledManifestRegistryProcessCaches);
30453146function isDeepFrozenJsonLike(value: unknown, seen = new WeakSet<object>()): boolean {
3247if (!value || typeof value !== "object") {
@@ -106,6 +121,38 @@ function formatFileSignature(
106121return `${filePath}:${signature.size}:${signature.mtimeMs}`;
107122}
108123124+function rememberInstalledPackageMetadata(
125+key: string | undefined,
126+metadata: InstalledPackageMetadata,
127+): InstalledPackageMetadata {
128+if (!key) {
129+return metadata;
130+}
131+installedPackageMetadataCache.set(key, metadata);
132+while (installedPackageMetadataCache.size > MAX_INSTALLED_PACKAGE_METADATA_CACHE_ENTRIES) {
133+const oldest = installedPackageMetadataCache.keys().next().value;
134+if (oldest === undefined) {
135+break;
136+}
137+installedPackageMetadataCache.delete(oldest);
138+}
139+return metadata;
140+}
141+142+function buildInstalledPackageMetadataCacheKey(params: {
143+packageJsonPath?: string;
144+record: InstalledPluginIndexRecord;
145+}): string | undefined {
146+if (!params.packageJsonPath || !params.record.packageJson?.hash) {
147+return undefined;
148+}
149+return hashJson({
150+packageJsonPath: path.resolve(params.packageJsonPath),
151+packageJson: params.record.packageJson,
152+packageChannel: params.record.packageChannel ?? null,
153+});
154+}
155+109156function buildInstalledManifestRegistryIndexKey(index: InstalledPluginIndex) {
110157const realpathCache = new Map<string, string>();
111158return {
@@ -418,11 +465,7 @@ function normalizePersistedPackageChannel(value: unknown): PluginPackageChannel
418465function resolveInstalledPackageMetadata(
419466record: InstalledPluginIndexRecord,
420467realpathCache: Map<string, string>,
421-): {
422-packageManifest?: OpenClawPackageManifest;
423-packageDependencies?: PluginDependencySpecMap;
424-packageOptionalDependencies?: PluginDependencySpecMap;
425-} {
468+): InstalledPackageMetadata {
426469const recordPackageChannel = normalizePersistedPackageChannel(record.packageChannel);
427470const fallbackPackageManifest = recordPackageChannel
428471 ? {
@@ -432,8 +475,16 @@ function resolveInstalledPackageMetadata(
432475const packageJsonPath = record.packageJson?.path
433476 ? resolvePackageJsonPath(record, realpathCache)
434477 : undefined;
478+const cacheKey = buildInstalledPackageMetadataCacheKey({ packageJsonPath, record });
479+const cached = cacheKey ? installedPackageMetadataCache.get(cacheKey) : undefined;
480+if (cached) {
481+return cached;
482+}
435483if (!packageJsonPath) {
436-return fallbackPackageManifest ? { packageManifest: fallbackPackageManifest } : {};
484+return rememberInstalledPackageMetadata(
485+cacheKey,
486+fallbackPackageManifest ? { packageManifest: fallbackPackageManifest } : {},
487+);
437488}
438489const packageJson = tryReadJsonSync<PackageManifest>(packageJsonPath);
439490if (packageJson) {
@@ -443,11 +494,11 @@ function resolveInstalledPackageMetadata(
443494optionalDependencies: packageJson.optionalDependencies,
444495});
445496if (!packageManifest) {
446-return {
497+return rememberInstalledPackageMetadata(cacheKey, {
447498 ...(fallbackPackageManifest ? { packageManifest: fallbackPackageManifest } : {}),
448499packageDependencies: dependencies.dependencies,
449500packageOptionalDependencies: dependencies.optionalDependencies,
450-};
501+});
451502}
452503const packageChannel = normalizePersistedPackageChannel(packageManifest.channel);
453504const channel =
@@ -458,16 +509,19 @@ function resolveInstalledPackageMetadata(
458509}
459510 : undefined;
460511const { channel: _ignoredChannel, ...packageManifestWithoutChannel } = packageManifest;
461-return {
512+return rememberInstalledPackageMetadata(cacheKey, {
462513packageManifest: {
463514 ...packageManifestWithoutChannel,
464515 ...(channel ? { channel } : {}),
465516},
466517packageDependencies: dependencies.dependencies,
467518packageOptionalDependencies: dependencies.optionalDependencies,
468-};
519+});
469520}
470-return fallbackPackageManifest ? { packageManifest: fallbackPackageManifest } : {};
521+return rememberInstalledPackageMetadata(
522+cacheKey,
523+fallbackPackageManifest ? { packageManifest: fallbackPackageManifest } : {},
524+);
471525}
472526473527function toPluginCandidate(
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。