refactor: let config validation use plugin metadata snapshot

This commit is contained in:
Shakker
2026-04-27 16:13:19 +01:00
parent 440fc73448
commit ca4f964547
2 changed files with 42 additions and 4 deletions

View File

@@ -234,4 +234,31 @@ describe("validateConfigObjectWithPlugins bundled allowlist compatibility", () =
expect(result.ok).toBe(true);
expect(mockLoadPluginManifestRegistry).toHaveBeenCalledOnce();
});
it("uses a provided plugin metadata snapshot during plugin validation", () => {
const result = validateConfigObjectWithPlugins(
{
plugins: {
entries: {
opik: {
enabled: true,
},
},
},
},
{
pluginMetadataSnapshot: {
manifestRegistry: createPluginConfigSchemaRegistry(),
},
},
);
expect(result.ok).toBe(true);
expect(mockLoadPluginManifestRegistry).not.toHaveBeenCalled();
if (result.ok) {
expect(result.config.plugins?.entries?.opik?.config).toEqual({
workspace: "default-workspace",
});
}
});
});

View File

@@ -16,6 +16,7 @@ import {
import { loadInstalledPluginIndexInstallRecordsSync } from "../plugins/installed-plugin-index-record-reader.js";
import { resolveManifestCommandAliasOwnerInRegistry } from "../plugins/manifest-command-aliases.js";
import type { PluginManifestRegistry } from "../plugins/manifest-registry.js";
import type { PluginMetadataSnapshot } from "../plugins/plugin-metadata-snapshot.js";
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
import { validateJsonSchemaValue } from "../plugins/schema-validator.js";
import { hasKind } from "../plugins/slots.js";
@@ -706,31 +707,39 @@ type ValidateConfigWithPluginsResult =
warnings: ConfigValidationIssue[];
};
type ValidateConfigWithPluginsParams = {
env?: NodeJS.ProcessEnv;
pluginValidation?: "full" | "skip";
pluginMetadataSnapshot?: Pick<PluginMetadataSnapshot, "manifestRegistry">;
};
export function validateConfigObjectWithPlugins(
raw: unknown,
params?: { env?: NodeJS.ProcessEnv; pluginValidation?: "full" | "skip" },
params?: ValidateConfigWithPluginsParams,
): ValidateConfigWithPluginsResult {
return validateConfigObjectWithPluginsBase(raw, {
applyDefaults: true,
env: params?.env,
pluginValidation: params?.pluginValidation ?? "full",
pluginMetadataSnapshot: params?.pluginMetadataSnapshot,
});
}
export function validateConfigObjectRawWithPlugins(
raw: unknown,
params?: { env?: NodeJS.ProcessEnv; pluginValidation?: "full" | "skip" },
params?: ValidateConfigWithPluginsParams,
): ValidateConfigWithPluginsResult {
return validateConfigObjectWithPluginsBase(raw, {
applyDefaults: false,
env: params?.env,
pluginValidation: params?.pluginValidation ?? "full",
pluginMetadataSnapshot: params?.pluginMetadataSnapshot,
});
}
function validateConfigObjectWithPluginsBase(
raw: unknown,
opts: { applyDefaults: boolean; env?: NodeJS.ProcessEnv; pluginValidation?: "full" | "skip" },
opts: ValidateConfigWithPluginsParams & { applyDefaults: boolean },
): ValidateConfigWithPluginsResult {
const base = opts.applyDefaults ? validateConfigObject(raw) : validateConfigObjectRaw(raw);
if (!base.ok) {
@@ -772,7 +781,9 @@ function validateConfigObjectWithPluginsBase(
>;
};
let registryInfo: RegistryInfo | null = null;
let registryInfo: RegistryInfo | null = opts.pluginMetadataSnapshot
? { registry: opts.pluginMetadataSnapshot.manifestRegistry }
: null;
let compatConfig: OpenClawConfig | null | undefined;
let compatPluginIds: ReadonlySet<string> | null = null;
let compatPluginIdsResolved = false;