





























@@ -91,7 +91,7 @@ export type InstalledPluginIndexRecord = {
9191packageJsonHash?: string;
9292rootDir: string;
9393origin: PluginManifestRecord["origin"];
94-enabled: boolean;
94+enabledByDefault?: boolean;
9595contributions: InstalledPluginIndexContributions;
9696compat: readonly PluginCompatCode[];
9797};
@@ -100,7 +100,8 @@ export type InstalledPluginIndex = {
100100version: typeof INSTALLED_PLUGIN_INDEX_VERSION;
101101hostContractVersion: string;
102102compatRegistryVersion: string;
103-generatedAt: string;
103+policyHash: string;
104+generatedAtMs: number;
104105refreshReason?: InstalledPluginIndexRefreshReason;
105106plugins: readonly InstalledPluginIndexRecord[];
106107diagnostics: readonly PluginDiagnostic[];
@@ -321,6 +322,40 @@ function resolveCompatRegistryVersion(): string {
321322);
322323}
323324325+function resolvePolicyHash(config: OpenClawConfig | undefined): string {
326+const normalized = normalizePluginsConfigWithResolver(config?.plugins);
327+const channelPolicy: Record<string, boolean> = {};
328+const channels = config?.channels;
329+if (channels && typeof channels === "object" && !Array.isArray(channels)) {
330+for (const [channelId, value] of Object.entries(channels)) {
331+if (value && typeof value === "object" && !Array.isArray(value)) {
332+const enabled = (value as Record<string, unknown>).enabled;
333+if (typeof enabled === "boolean") {
334+channelPolicy[channelId] = enabled;
335+}
336+}
337+}
338+}
339+return hashJson({
340+plugins: {
341+enabled: normalized.enabled,
342+allow: normalized.allow,
343+deny: normalized.deny,
344+slots: normalized.slots,
345+entries: Object.fromEntries(
346+Object.entries(normalized.entries)
347+.flatMap(([pluginId, entry]) =>
348+typeof entry.enabled === "boolean" ? [[pluginId, entry.enabled] as const] : [],
349+)
350+.toSorted(([left], [right]) => left.localeCompare(right)),
351+),
352+},
353+channels: Object.fromEntries(
354+Object.entries(channelPolicy).toSorted(([left], [right]) => left.localeCompare(right)),
355+),
356+});
357+}
358+324359function resolveRegistry(params: LoadInstalledPluginIndexParams): {
325360registry: PluginManifestRegistry;
326361candidates: readonly PluginCandidate[];
@@ -365,9 +400,8 @@ function buildInstalledPluginIndex(
365400const env = params.env ?? process.env;
366401const { candidates, registry } = resolveRegistry(params);
367402const candidateByRootDir = buildCandidateLookup(candidates);
368-const normalizedConfig = normalizePluginsConfigWithResolver(params.config?.plugins);
369403const diagnostics: PluginDiagnostic[] = [...registry.diagnostics];
370-const generatedAt = (params.now?.() ?? new Date()).toISOString();
404+const generatedAtMs = (params.now?.() ?? new Date()).getTime();
371405const plugins = registry.plugins.map((record): InstalledPluginIndexRecord => {
372406const candidate = candidateByRootDir.get(record.rootDir);
373407const packageJsonPath = resolvePackageJsonPath(candidate);
@@ -388,24 +422,18 @@ function buildInstalledPluginIndex(
388422required: false,
389423})
390424 : undefined;
391-const enabled = resolveEffectiveEnableState({
392-id: record.id,
393-origin: record.origin,
394-config: normalizedConfig,
395-rootConfig: params.config,
396-enabledByDefault: record.enabledByDefault,
397-}).enabled;
398-399425const indexRecord: InstalledPluginIndexRecord = {
400426pluginId: record.id,
401427manifestPath: record.manifestPath,
402428 manifestHash,
403429rootDir: record.rootDir,
404430origin: record.origin,
405- enabled,
406431contributions: buildContributions(record),
407432compat: collectCompatCodes(record),
408433};
434+if (record.enabledByDefault === true) {
435+indexRecord.enabledByDefault = true;
436+}
409437if (candidate?.packageName) {
410438indexRecord.packageName = candidate.packageName;
411439}
@@ -432,7 +460,8 @@ function buildInstalledPluginIndex(
432460version: INSTALLED_PLUGIN_INDEX_VERSION,
433461hostContractVersion: resolveCompatibilityHostVersion(env),
434462compatRegistryVersion: resolveCompatRegistryVersion(),
435- generatedAt,
463+policyHash: resolvePolicyHash(params.config),
464+ generatedAtMs,
436465 ...(params.refreshReason ? { refreshReason: params.refreshReason } : {}),
437466 plugins,
438467 diagnostics,
@@ -459,8 +488,19 @@ export function listInstalledPluginRecords(
459488460489export function listEnabledInstalledPluginRecords(
461490index: InstalledPluginIndex,
491+config?: OpenClawConfig,
462492): readonly InstalledPluginIndexRecord[] {
463-return index.plugins.filter((plugin) => plugin.enabled);
493+const normalizedConfig = normalizePluginsConfigWithResolver(config?.plugins);
494+return index.plugins.filter(
495+(plugin) =>
496+resolveEffectiveEnableState({
497+id: plugin.pluginId,
498+origin: plugin.origin,
499+config: normalizedConfig,
500+rootConfig: config,
501+enabledByDefault: plugin.enabledByDefault,
502+}).enabled,
503+);
464504}
465505466506export function getInstalledPluginRecord(
@@ -470,21 +510,38 @@ export function getInstalledPluginRecord(
470510return index.plugins.find((plugin) => plugin.pluginId === pluginId);
471511}
472512473-export function isInstalledPluginEnabled(index: InstalledPluginIndex, pluginId: string): boolean {
474-return getInstalledPluginRecord(index, pluginId)?.enabled === true;
513+export function isInstalledPluginEnabled(
514+index: InstalledPluginIndex,
515+pluginId: string,
516+config?: OpenClawConfig,
517+): boolean {
518+const record = getInstalledPluginRecord(index, pluginId);
519+if (!record) {
520+return false;
521+}
522+const normalizedConfig = normalizePluginsConfigWithResolver(config?.plugins);
523+return resolveEffectiveEnableState({
524+id: record.pluginId,
525+origin: record.origin,
526+config: normalizedConfig,
527+rootConfig: config,
528+enabledByDefault: record.enabledByDefault,
529+}).enabled;
475530}
476531477532function resolveContributionRecordSet(
478533index: InstalledPluginIndex,
479-options: { includeDisabled?: boolean },
534+options: { includeDisabled?: boolean; config?: OpenClawConfig },
480535): readonly InstalledPluginIndexRecord[] {
481-return options.includeDisabled ? index.plugins : listEnabledInstalledPluginRecords(index);
536+return options.includeDisabled
537+ ? index.plugins
538+ : listEnabledInstalledPluginRecords(index, options.config);
482539}
483540484541export function listInstalledPluginContributionIds(
485542index: InstalledPluginIndex,
486543contribution: InstalledPluginContributionKey,
487-options: { includeDisabled?: boolean } = {},
544+options: { includeDisabled?: boolean; config?: OpenClawConfig } = {},
488545): readonly string[] {
489546return sortUnique(
490547resolveContributionRecordSet(index, options).flatMap(
@@ -497,7 +554,7 @@ export function resolveInstalledPluginContributionOwners(
497554index: InstalledPluginIndex,
498555contribution: InstalledPluginContributionKey,
499556matches: string | ((contributionId: string) => boolean),
500-options: { includeDisabled?: boolean } = {},
557+options: { includeDisabled?: boolean; config?: OpenClawConfig } = {},
501558): readonly string[] {
502559const matcher =
503560typeof matches === "string" ? (contributionId: string) => contributionId === matches : matches;
@@ -598,6 +655,9 @@ export function diffInstalledPluginIndexInvalidationReasons(
598655if (previous.compatRegistryVersion !== current.compatRegistryVersion) {
599656reasons.add("compat-registry-changed");
600657}
658+if (previous.policyHash !== current.policyHash) {
659+reasons.add("policy-changed");
660+}
601661602662const previousByPluginId = new Map(previous.plugins.map((plugin) => [plugin.pluginId, plugin]));
603663const currentByPluginId = new Map(current.plugins.map((plugin) => [plugin.pluginId, plugin]));
@@ -614,9 +674,6 @@ export function diffInstalledPluginIndexInvalidationReasons(
614674) {
615675reasons.add("source-changed");
616676}
617-if (previousPlugin.enabled !== currentPlugin.enabled) {
618-reasons.add("policy-changed");
619-}
620677if (previousPlugin.manifestHash !== currentPlugin.manifestHash) {
621678reasons.add("stale-manifest");
622679}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。