refactor: route plugin metadata consumers through snapshots

This commit is contained in:
Peter Steinberger
2026-05-02 08:18:45 +01:00
parent 06b528216b
commit 3e15090c7e
16 changed files with 156 additions and 110 deletions

View File

@@ -10,8 +10,7 @@ import {
normalizePluginsConfigWithResolver,
resolveEffectivePluginActivationState,
} from "../plugins/config-policy.js";
import type { PluginManifestRegistry } from "../plugins/manifest-registry.js";
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
import { loadPluginMetadataSnapshot } from "../plugins/plugin-metadata-snapshot.js";
import { isRecord } from "../utils.js";
import { loadEmbeddedPiMcpConfig } from "./embedded-pi-mcp.js";
@@ -69,33 +68,6 @@ function loadBundleSettingsFile(params: {
}
}
function buildRegistryPluginIdAliases(
registry: PluginManifestRegistry,
): Readonly<Record<string, string>> {
return Object.fromEntries(
registry.plugins
.flatMap((record) => [
...(record.providers ?? [])
.filter((providerId) => providerId !== record.id)
.map((providerId) => [providerId, record.id] as const),
...(record.legacyPluginIds ?? []).map(
(legacyPluginId) => [legacyPluginId, record.id] as const,
),
])
.toSorted(([left], [right]) => left.localeCompare(right)),
);
}
function createRegistryPluginIdNormalizer(
registry: PluginManifestRegistry,
): (id: string) => string {
const aliases = buildRegistryPluginIdAliases(registry);
return (id: string) => {
const trimmed = id.trim();
return aliases[trimmed] ?? trimmed;
};
}
export function loadEnabledBundlePiSettingsSnapshot(params: {
cwd: string;
cfg?: OpenClawConfig;
@@ -104,18 +76,19 @@ export function loadEnabledBundlePiSettingsSnapshot(params: {
if (!workspaceDir) {
return {};
}
const registry = loadPluginManifestRegistryForPluginRegistry({
const metadataSnapshot = loadPluginMetadataSnapshot({
workspaceDir,
config: params.cfg,
includeDisabled: true,
config: params.cfg ?? {},
env: process.env,
});
const registry = metadataSnapshot.manifestRegistry;
if (registry.plugins.length === 0) {
return {};
}
const normalizedPlugins = normalizePluginsConfigWithResolver(
params.cfg?.plugins,
createRegistryPluginIdNormalizer(registry),
metadataSnapshot.normalizePluginId,
);
let snapshot: PiSettingsSnapshot = {};

View File

@@ -79,6 +79,42 @@ vi.mock("../plugins/plugin-registry.js", async () => {
};
});
vi.mock("../plugins/plugin-metadata-snapshot.js", async () => {
const fs = await import("node:fs");
const path = await import("node:path");
const loadRegistry = (params: { workspaceDir?: string }) => {
const rootDir = path.join(
params.workspaceDir ?? "",
".openclaw",
"extensions",
"claude-bundle",
);
if (!fs.existsSync(path.join(rootDir, ".claude-plugin", "plugin.json"))) {
return { plugins: [], diagnostics: [] };
}
const resolvedRootDir = fs.realpathSync(rootDir);
return {
diagnostics: [],
plugins: [
{
id: "claude-bundle",
origin: "workspace",
format: "bundle",
bundleFormat: "claude",
settingsFiles: ["settings.json"],
rootDir: resolvedRootDir,
},
],
};
};
return {
loadPluginMetadataSnapshot: (params: { workspaceDir?: string }) => ({
manifestRegistry: loadRegistry(params),
normalizePluginId: (id: string) => id.trim(),
}),
};
});
vi.mock("./embedded-pi-mcp.js", async () => {
const fs = await import("node:fs");
const path = await import("node:path");

View File

@@ -9,7 +9,7 @@ import {
type PluginManifestRecord,
type PluginManifestRegistry,
} from "../plugins/manifest-registry.js";
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
import { loadPluginMetadataSnapshot } from "../plugins/plugin-metadata-snapshot.js";
import { resolveOwningPluginIdsForModelRef } from "../plugins/providers.js";
import { resolvePluginSetupAutoEnableReasons } from "../plugins/setup-registry.js";
import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
@@ -220,16 +220,13 @@ function resolvePluginsWithOwnedToolConfig(
function resolvePluginIdForConfiguredWebFetchProvider(
providerId: string | undefined,
env: NodeJS.ProcessEnv,
registry: PluginManifestRegistry,
): string | undefined {
const normalizedProviderId = normalizeOptionalLowercaseString(providerId);
if (!normalizedProviderId) {
return undefined;
}
return loadPluginManifestRegistryForPluginRegistry({
env,
includeDisabled: true,
}).plugins.find(
return registry.plugins.find(
(plugin) =>
plugin.origin === "bundled" &&
(plugin.contracts?.webFetchProviders ?? []).some(
@@ -623,7 +620,7 @@ export function resolveConfiguredPluginAutoEnableCandidates(params: {
: undefined;
const webFetchPluginId = resolvePluginIdForConfiguredWebFetchProvider(
webFetchProvider,
params.env,
params.registry,
);
if (webFetchPluginId) {
changes.push({
@@ -869,11 +866,10 @@ export function resolvePluginAutoEnableManifestRegistry(params: {
return (
params.manifestRegistry ??
(configMayNeedPluginManifestRegistry(params.config, params.env)
? loadPluginManifestRegistryForPluginRegistry({
? loadPluginMetadataSnapshot({
config: params.config,
env: params.env,
includeDisabled: true,
})
}).manifestRegistry
: EMPTY_PLUGIN_MANIFEST_REGISTRY)
);
}

View File

@@ -34,6 +34,12 @@ vi.mock("../plugins/plugin-registry.js", () => ({
mockLoadPluginManifestRegistry(...args),
}));
vi.mock("../plugins/plugin-metadata-snapshot.js", () => ({
loadPluginMetadataSnapshot: (...args: unknown[]) => ({
manifestRegistry: mockLoadPluginManifestRegistry(...args),
}),
}));
vi.mock("../plugins/current-plugin-metadata-snapshot.js", () => ({
getCurrentPluginMetadataSnapshot: (...args: unknown[]) =>
mockGetCurrentPluginMetadataSnapshot(...args),
@@ -309,7 +315,7 @@ describe("loadGatewayRuntimeConfigSchema", () => {
expect(mockLoadPluginManifestRegistry).toHaveBeenCalledTimes(3);
for (const call of mockLoadPluginManifestRegistry.mock.calls) {
expect(call[0]).toMatchObject({ includeDisabled: true });
expect(call[0]).toHaveProperty("config");
expect(call[0]).not.toHaveProperty("bundledChannelConfigCollector");
}
expect(getActivePluginRegistry()).toBe(activeRegistry);

View File

@@ -1,6 +1,6 @@
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent-scope.js";
import { getCurrentPluginMetadataSnapshot } from "../plugins/current-plugin-metadata-snapshot.js";
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
import { loadPluginMetadataSnapshot } from "../plugins/plugin-metadata-snapshot.js";
import {
collectChannelSchemaMetadata,
collectPluginSchemaMetadata,
@@ -15,14 +15,11 @@ function loadManifestRegistry(config: OpenClawConfig, env?: NodeJS.ProcessEnv) {
if (currentSnapshot) {
return currentSnapshot.manifestRegistry;
}
return loadPluginManifestRegistryForPluginRegistry({
return loadPluginMetadataSnapshot({
config,
// Bundled channel schemas are already generated into the base schema; avoid
// loading plugin config-schema modules on every config.get/config.schema.
env,
env: env ?? process.env,
workspaceDir,
includeDisabled: true,
});
}).manifestRegistry;
}
export function loadGatewayRuntimeConfigSchema(): ConfigSchemaResponse {

View File

@@ -120,12 +120,23 @@ vi.mock("../plugins/plugin-registry.js", () => ({
loadPluginManifestRegistryForPluginRegistry: () => mockLoadPluginManifestRegistry(),
}));
vi.mock("../plugins/plugin-metadata-snapshot.js", () => ({
loadPluginMetadataSnapshot: () => ({
manifestRegistry: mockLoadPluginManifestRegistry(),
}),
}));
vi.mock("../plugins/doctor-contract-registry.js", () => ({
collectRelevantDoctorPluginIds: () => [],
listPluginDoctorLegacyConfigRules: () => [],
applyPluginDoctorCompatibilityMigrations: () => ({ next: null, changes: [] }),
}));
vi.mock("../secrets/target-registry-data.js", () => ({
getCoreSecretTargetRegistry: () => [],
getSecretTargetRegistry: () => [],
}));
vi.mock("../channels/plugins/legacy-config.js", () => ({
collectChannelLegacyConfigRules: () => [],
}));

View File

@@ -16,8 +16,10 @@ 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 {
loadPluginMetadataSnapshot,
type PluginMetadataSnapshot,
} from "../plugins/plugin-metadata-snapshot.js";
import { validateJsonSchemaValue } from "../plugins/schema-validator.js";
import { hasKind } from "../plugins/slots.js";
import { collectLegacySecretRefEnvMarkerCandidates } from "../secrets/legacy-secretref-env-marker.js";
@@ -821,12 +823,11 @@ function validateConfigObjectWithPluginsBase(
return registryInfo;
}
const workspaceDir = resolveAgentWorkspaceDir(config, resolveDefaultAgentId(config));
const registry = loadPluginManifestRegistryForPluginRegistry({
const registry = loadPluginMetadataSnapshot({
config,
workspaceDir: workspaceDir ?? undefined,
env: opts.env,
includeDisabled: true,
});
env: opts.env ?? process.env,
}).manifestRegistry;
registryInfo = { registry };
return registryInfo;
};

View File

@@ -2,7 +2,7 @@ import { z } from "zod";
import { collectBundledChannelConfigs } from "../plugins/bundled-channel-config-metadata.js";
import type { PluginManifestRegistry } from "../plugins/manifest-registry.js";
import type { PluginManifest } from "../plugins/manifest.js";
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
import { loadPluginMetadataSnapshot } from "../plugins/plugin-metadata-snapshot.js";
import type { ChannelsConfig } from "./types.channels.js";
import { ChannelHeartbeatVisibilitySchema } from "./zod-schema.channels.js";
import { ContextVisibilityModeSchema, GroupPolicySchema } from "./zod-schema.core.js";
@@ -87,9 +87,7 @@ function normalizeBundledChannelConfigs(
let next: ChannelsConfig | undefined;
let registry: PluginManifestRegistry | undefined;
for (const channelId of Object.keys(value)) {
registry ??= loadPluginManifestRegistryForPluginRegistry({
includeDisabled: true,
});
registry ??= loadPluginMetadataSnapshot({ config: {}, env: process.env }).manifestRegistry;
const runtimeSchema = getDirectChannelRuntimeSchema(channelId, registry);
if (!runtimeSchema) {
continue;

View File

@@ -4,6 +4,7 @@ const pluginRegistryMocks = vi.hoisted(() => ({
loadPluginManifestRegistryForInstalledIndex: vi.fn(),
loadPluginManifestRegistryForPluginRegistry: vi.fn(),
loadPluginRegistrySnapshot: vi.fn(() => ({ plugins: [] })),
loadPluginMetadataSnapshot: vi.fn(),
}));
vi.mock("./manifest-registry-installed.js", () => ({
@@ -23,6 +24,14 @@ vi.mock("../plugins/plugin-registry.js", () => ({
loadPluginRegistrySnapshot: pluginRegistryMocks.loadPluginRegistrySnapshot,
}));
vi.mock("./plugin-metadata-snapshot.js", () => ({
loadPluginMetadataSnapshot: pluginRegistryMocks.loadPluginMetadataSnapshot,
}));
vi.mock("../plugins/plugin-metadata-snapshot.js", () => ({
loadPluginMetadataSnapshot: pluginRegistryMocks.loadPluginMetadataSnapshot,
}));
vi.resetModules();
const {
@@ -53,6 +62,10 @@ function setManifestPlugins(plugins: Array<Record<string, unknown>>) {
pluginRegistryMocks.loadPluginManifestRegistryForPluginRegistry.mockReturnValue({
plugins,
});
pluginRegistryMocks.loadPluginMetadataSnapshot.mockReturnValue({
plugins,
manifestRegistry: { plugins },
});
}
function expectResolvedProviderAuthChoices(params: {
@@ -88,6 +101,11 @@ describe("provider auth choice manifest helpers", () => {
});
pluginRegistryMocks.loadPluginRegistrySnapshot.mockReset();
pluginRegistryMocks.loadPluginRegistrySnapshot.mockReturnValue({ plugins: [] });
pluginRegistryMocks.loadPluginMetadataSnapshot.mockReset();
pluginRegistryMocks.loadPluginMetadataSnapshot.mockReturnValue({
plugins: [],
manifestRegistry: { plugins: [] },
});
resetProviderAuthAliasMapCacheForTest();
});
@@ -572,7 +590,7 @@ describe("provider auth choice manifest helpers", () => {
]);
const resolvedProviderId = resolveProviderIdForAuth("fixture-provider-plan");
expect(pluginRegistryMocks.loadPluginManifestRegistryForPluginRegistry).toHaveBeenCalled();
expect(pluginRegistryMocks.loadPluginMetadataSnapshot).toHaveBeenCalled();
expect(resolvedProviderId).toBe("fixture-provider");
expect(
resolveManifestProviderApiKeyChoice({

View File

@@ -3,8 +3,8 @@ import type { OpenClawConfig } from "../config/types.openclaw.js";
import { sanitizeForLog } from "../terminal/ansi.js";
import { normalizePluginsConfig, resolveEffectiveEnableState } from "./config-state.js";
import type { PluginManifestRecord } from "./manifest-registry.js";
import { loadPluginMetadataSnapshot } from "./plugin-metadata-snapshot.js";
import type { PluginOrigin } from "./plugin-origin.types.js";
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
export type ProviderAuthChoiceMetadata = {
pluginId: string;
@@ -180,12 +180,12 @@ function resolveManifestProviderAuthChoiceCandidates(params?: {
env?: NodeJS.ProcessEnv;
includeUntrustedWorkspacePlugins?: boolean;
}): ProviderAuthChoiceCandidate[] {
const registry = loadPluginManifestRegistryForPluginRegistry({
config: params?.config,
const metadataSnapshot = loadPluginMetadataSnapshot({
config: params?.config ?? {},
workspaceDir: params?.workspaceDir,
env: params?.env,
includeDisabled: true,
env: params?.env ?? process.env,
});
const registry = metadataSnapshot.manifestRegistry;
const normalizedConfig = normalizePluginsConfig(params?.config?.plugins);
return registry.plugins.flatMap((plugin) => {
if (

View File

@@ -3,6 +3,7 @@ import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
const mocks = vi.hoisted(() => ({
loadPluginRegistrySnapshot: vi.fn(),
loadPluginManifestRegistryForInstalledIndex: vi.fn(),
loadPluginMetadataSnapshot: vi.fn(),
}));
vi.mock("./plugin-registry.js", () => ({
@@ -19,6 +20,10 @@ vi.mock("./manifest-registry-installed.js", () => ({
mocks.loadPluginManifestRegistryForInstalledIndex(...args),
}));
vi.mock("./plugin-metadata-snapshot.js", () => ({
loadPluginMetadataSnapshot: (...args: unknown[]) => mocks.loadPluginMetadataSnapshot(...args),
}));
let resolveManifestDeclaredWebProviderCandidatePluginIds: typeof import("./web-provider-resolution-shared.js").resolveManifestDeclaredWebProviderCandidatePluginIds;
describe("resolveManifestDeclaredWebProviderCandidatePluginIds", () => {
@@ -52,6 +57,10 @@ describe("resolveManifestDeclaredWebProviderCandidatePluginIds", () => {
],
diagnostics: [],
});
mocks.loadPluginMetadataSnapshot.mockReset();
mocks.loadPluginMetadataSnapshot.mockImplementation((...args: unknown[]) => ({
plugins: mocks.loadPluginManifestRegistryForInstalledIndex(...args).plugins,
}));
});
it("treats explicit empty plugin scopes as scoped-empty", () => {
@@ -73,11 +82,7 @@ describe("resolveManifestDeclaredWebProviderCandidatePluginIds", () => {
onlyPluginIds: ["missing-plugin"],
}),
).toEqual([]);
expect(mocks.loadPluginManifestRegistryForInstalledIndex).toHaveBeenCalledWith(
expect.objectContaining({
pluginIds: ["missing-plugin"],
}),
);
expect(mocks.loadPluginMetadataSnapshot).toHaveBeenCalledOnce();
});
it("keeps origin filters with no declared web candidates scoped-empty", () => {
@@ -110,7 +115,7 @@ describe("resolveManifestDeclaredWebProviderCandidatePluginIds", () => {
configKey: "webSearch",
}),
).toEqual(["alpha", "beta"]);
expect(mocks.loadPluginRegistrySnapshot).toHaveBeenCalledTimes(1);
expect(mocks.loadPluginMetadataSnapshot).toHaveBeenCalledTimes(1);
expect(mocks.loadPluginManifestRegistryForInstalledIndex).toHaveBeenCalledTimes(1);
});
});

View File

@@ -1,7 +1,7 @@
import { resolveBundledPluginCompatibleLoadValues } from "./activation-context.js";
import type { PluginLoadOptions } from "./loader.js";
import type { PluginManifestRecord } from "./manifest-registry.js";
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
import { loadPluginMetadataSnapshot } from "./plugin-metadata-snapshot.js";
import { createPluginIdScopeSet, normalizePluginIdScope } from "./plugin-scope.js";
export type WebProviderContract = "webSearchProviders" | "webFetchProviders";
@@ -66,13 +66,13 @@ function loadInstalledWebProviderManifestRecords(params: {
env?: PluginLoadOptions["env"];
pluginIds?: readonly string[];
}): readonly PluginManifestRecord[] {
return loadPluginManifestRegistryForPluginRegistry({
config: params.config,
const records = loadPluginMetadataSnapshot({
config: params.config ?? {},
workspaceDir: params.workspaceDir,
env: params.env,
pluginIds: params.pluginIds,
includeDisabled: true,
env: params.env ?? process.env,
}).plugins;
const pluginIdSet = createPluginIdScopeSet(params.pluginIds);
return pluginIdSet ? records.filter((plugin) => pluginIdSet.has(plugin.id)) : records;
}
export function resolveManifestDeclaredWebProviderCandidatePluginIds(params: {

View File

@@ -1,6 +1,6 @@
import type { OpenClawConfig } from "../config/types.openclaw.js";
import type { PluginManifestRecord } from "./manifest-registry.js";
import { loadPluginManifestRegistryForPluginRegistry } from "./plugin-registry.js";
import { loadPluginMetadataSnapshot } from "./plugin-metadata-snapshot.js";
function hasConfiguredCredentialValue(value: unknown): boolean {
if (typeof value === "string") {
@@ -42,10 +42,9 @@ function hasManifestWebSearchEnvCredentialCandidate(params: {
if (!env) {
return false;
}
return loadPluginManifestRegistryForPluginRegistry({
return loadPluginMetadataSnapshot({
config: params.config,
env,
includeDisabled: true,
}).plugins.some((plugin) => {
if (params.origin && plugin.origin !== params.origin) {
return false;

View File

@@ -18,6 +18,10 @@ const pluginRegistryMocks = vi.hoisted(() => {
loadPluginManifestRegistryForInstalledIndex: loadManifestRegistry,
loadPluginManifestRegistryForPluginRegistry: loadManifestRegistry,
loadPluginRegistrySnapshot: vi.fn(() => ({ plugins: [] })),
loadPluginMetadataSnapshot: vi.fn(() => ({
plugins: loadManifestRegistry().plugins,
manifestRegistry: loadManifestRegistry(),
})),
};
});
@@ -32,6 +36,10 @@ vi.mock("../plugins/plugin-registry.js", () => ({
loadPluginRegistrySnapshot: pluginRegistryMocks.loadPluginRegistrySnapshot,
}));
vi.mock("../plugins/plugin-metadata-snapshot.js", () => ({
loadPluginMetadataSnapshot: pluginRegistryMocks.loadPluginMetadataSnapshot,
}));
describe("channel env vars dynamic manifest metadata", () => {
beforeEach(() => {
vi.resetModules();
@@ -42,6 +50,7 @@ describe("channel env vars dynamic manifest metadata", () => {
});
pluginRegistryMocks.loadPluginRegistrySnapshot.mockReset();
pluginRegistryMocks.loadPluginRegistrySnapshot.mockReturnValue({ plugins: [] });
pluginRegistryMocks.loadPluginMetadataSnapshot.mockClear();
});
it("includes later-installed plugin env vars without a bundled generated map", async () => {

View File

@@ -1,5 +1,5 @@
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
import { loadPluginMetadataSnapshot } from "../plugins/plugin-metadata-snapshot.js";
export { isSafeChannelEnvVarTriggerName } from "./channel-env-var-names.js";
type ChannelEnvVarLookupParams = {
@@ -32,14 +32,13 @@ function appendUniqueEnvVarCandidates(
export function resolveChannelEnvVars(
params?: ChannelEnvVarLookupParams,
): Record<string, readonly string[]> {
const registry = loadPluginManifestRegistryForPluginRegistry({
config: params?.config,
const snapshot = loadPluginMetadataSnapshot({
config: params?.config ?? {},
workspaceDir: params?.workspaceDir,
env: params?.env,
includeDisabled: true,
env: params?.env ?? process.env,
});
const candidates: Record<string, string[]> = {};
for (const plugin of registry.plugins) {
for (const plugin of snapshot.plugins) {
if (!plugin.channelEnvVars) {
continue;
}

View File

@@ -1,5 +1,5 @@
import type { PluginManifestRecord } from "../plugins/manifest-registry.js";
import { loadPluginManifestRegistryForPluginRegistry } from "../plugins/plugin-registry.js";
import { loadPluginMetadataSnapshot } from "../plugins/plugin-metadata-snapshot.js";
import { loadBundledChannelSecretContractApi } from "./channel-contract-api.js";
import type { SecretTargetRegistryEntry } from "./target-registry-types.js";
@@ -47,13 +47,11 @@ function hasWebProviderContract(
return (plugin.contracts?.[contract]?.length ?? 0) > 0;
}
function listBundledWebProviderSecretTargetRegistryEntries(): SecretTargetRegistryEntry[] {
function listBundledWebProviderSecretTargetRegistryEntries(
bundledPlugins: readonly PluginManifestRecord[],
): SecretTargetRegistryEntry[] {
const entries: SecretTargetRegistryEntry[] = [];
for (const record of loadPluginManifestRegistryForPluginRegistry({ includeDisabled: true })
.plugins) {
if (record.origin !== "bundled") {
continue;
}
for (const record of bundledPlugins) {
for (const config of WEB_PROVIDER_SECRET_CONFIGS) {
if (
hasWebProviderContract(record, config.contract) &&
@@ -66,14 +64,12 @@ function listBundledWebProviderSecretTargetRegistryEntries(): SecretTargetRegist
return entries.toSorted((left, right) => left.id.localeCompare(right.id));
}
function listBundledPluginConfigSecretTargetRegistryEntries(): SecretTargetRegistryEntry[] {
function listBundledPluginConfigSecretTargetRegistryEntries(
bundledPlugins: readonly PluginManifestRecord[],
): SecretTargetRegistryEntry[] {
const entries: SecretTargetRegistryEntry[] = [];
const seen = new Set<string>();
for (const record of loadPluginManifestRegistryForPluginRegistry({ includeDisabled: true })
.plugins) {
if (record.origin !== "bundled") {
continue;
}
for (const record of bundledPlugins) {
const secretInputs = record.configContracts?.secretInputs?.paths ?? [];
for (const secretInput of secretInputs) {
const entry = createPluginOpenClawConfigSecretTargetEntry(record.id, secretInput.path);
@@ -88,14 +84,12 @@ function listBundledPluginConfigSecretTargetRegistryEntries(): SecretTargetRegis
return entries.toSorted((left, right) => left.id.localeCompare(right.id));
}
function listChannelSecretTargetRegistryEntries(): SecretTargetRegistryEntry[] {
function listChannelSecretTargetRegistryEntries(
bundledPlugins: readonly PluginManifestRecord[],
): SecretTargetRegistryEntry[] {
const entries: SecretTargetRegistryEntry[] = [];
for (const record of loadPluginManifestRegistryForPluginRegistry({ includeDisabled: true })
.plugins) {
if (record.origin !== "bundled") {
continue;
}
for (const record of bundledPlugins) {
const channelIds = record.channels;
if (channelIds.length === 0) {
continue;
@@ -455,11 +449,15 @@ export function getSecretTargetRegistry(): SecretTargetRegistryEntry[] {
if (cachedSecretTargetRegistry) {
return cachedSecretTargetRegistry;
}
const bundledPlugins = loadPluginMetadataSnapshot({
config: {},
env: process.env,
}).plugins.filter((record) => record.origin === "bundled");
cachedSecretTargetRegistry = [
...CORE_SECRET_TARGET_REGISTRY,
...listBundledWebProviderSecretTargetRegistryEntries(),
...listBundledPluginConfigSecretTargetRegistryEntries(),
...listChannelSecretTargetRegistryEntries(),
...listBundledWebProviderSecretTargetRegistryEntries(bundledPlugins),
...listBundledPluginConfigSecretTargetRegistryEntries(bundledPlugins),
...listChannelSecretTargetRegistryEntries(bundledPlugins),
];
return cachedSecretTargetRegistry;
}