From d251932fcfd60e205e80bf7e9abdb4af63582e6f Mon Sep 17 00:00:00 2001 From: Shakker Date: Sun, 26 Apr 2026 04:55:05 +0100 Subject: [PATCH] refactor: keep manifest contracts on plugin index --- .../shared/legacy-web-search-migrate.ts | 6 +- src/plugins/contracts/loader.contract.test.ts | 2 +- .../contracts/registry.contract.test.ts | 6 +- src/plugins/contracts/registry.ts | 6 +- src/plugins/manifest-registry.ts | 89 +------------------ src/plugins/providers.test.ts | 23 ----- 6 files changed, 8 insertions(+), 124 deletions(-) diff --git a/src/commands/doctor/shared/legacy-web-search-migrate.ts b/src/commands/doctor/shared/legacy-web-search-migrate.ts index 392d61c3f54..cbca3338e48 100644 --- a/src/commands/doctor/shared/legacy-web-search-migrate.ts +++ b/src/commands/doctor/shared/legacy-web-search-migrate.ts @@ -1,9 +1,7 @@ import { mergeMissing } from "../../../config/legacy.shared.js"; import type { OpenClawConfig } from "../../../config/types.openclaw.js"; -import { - loadPluginManifestRegistry, - resolveManifestContractOwnerPluginId, -} from "../../../plugins/manifest-registry.js"; +import { loadPluginManifestRegistry } from "../../../plugins/manifest-registry.js"; +import { resolveManifestContractOwnerPluginId } from "../../../plugins/plugin-registry.js"; import { cloneRecord, ensureRecord, diff --git a/src/plugins/contracts/loader.contract.test.ts b/src/plugins/contracts/loader.contract.test.ts index afc94461d51..4dd9831c87b 100644 --- a/src/plugins/contracts/loader.contract.test.ts +++ b/src/plugins/contracts/loader.contract.test.ts @@ -1,7 +1,7 @@ import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { uniqueSortedStrings } from "../../../test/helpers/plugins/contracts-testkit.js"; import { withBundledPluginAllowlistCompat } from "../bundled-compat.js"; -import { resolveManifestContractPluginIds } from "../manifest-registry.js"; +import { resolveManifestContractPluginIds } from "../plugin-registry.js"; import { __testing as providerTesting } from "../providers.js"; import { resolveBundledContractSnapshotPluginIds } from "./inventory/bundled-capability-metadata.js"; import { providerContractCompatPluginIds } from "./registry.js"; diff --git a/src/plugins/contracts/registry.contract.test.ts b/src/plugins/contracts/registry.contract.test.ts index 51ca68a1a2e..f8c38b8125e 100644 --- a/src/plugins/contracts/registry.contract.test.ts +++ b/src/plugins/contracts/registry.contract.test.ts @@ -1,9 +1,7 @@ import { describe, expect, it } from "vitest"; import { uniqueSortedStrings } from "../../../test/helpers/plugins/contracts-testkit.js"; -import { - loadPluginManifestRegistry, - resolveManifestContractPluginIds, -} from "../manifest-registry.js"; +import { loadPluginManifestRegistry } from "../manifest-registry.js"; +import { resolveManifestContractPluginIds } from "../plugin-registry.js"; import { pluginRegistrationContractRegistry, providerContractLoadError, diff --git a/src/plugins/contracts/registry.ts b/src/plugins/contracts/registry.ts index 6d13d204c29..0875e6cdd15 100644 --- a/src/plugins/contracts/registry.ts +++ b/src/plugins/contracts/registry.ts @@ -1,10 +1,8 @@ import { normalizeProviderId } from "../../agents/provider-id.js"; import { normalizeLowercaseStringOrEmpty } from "../../shared/string-coerce.js"; import { loadBundledCapabilityRuntimeRegistry } from "../bundled-capability-runtime.js"; -import { - loadPluginManifestRegistry, - resolveManifestContractPluginIds, -} from "../manifest-registry.js"; +import { loadPluginManifestRegistry } from "../manifest-registry.js"; +import { resolveManifestContractPluginIds } from "../plugin-registry.js"; import { resolveBundledExplicitProviderContractsFromPublicArtifacts } from "../provider-contract-public-artifacts.js"; import type { ImageGenerationProviderPlugin, diff --git a/src/plugins/manifest-registry.ts b/src/plugins/manifest-registry.ts index 51e26fba39b..cf8210bfd5a 100644 --- a/src/plugins/manifest-registry.ts +++ b/src/plugins/manifest-registry.ts @@ -3,10 +3,7 @@ import path from "node:path"; import type { OpenClawConfig } from "../config/types.js"; import type { PluginInstallRecord } from "../config/types.plugins.js"; import { isBlockedObjectKey } from "../infra/prototype-keys.js"; -import { - normalizeOptionalLowercaseString, - normalizeOptionalString, -} from "../shared/string-coerce.js"; +import { normalizeOptionalString } from "../shared/string-coerce.js"; import { normalizeOptionalTrimmedStringList } from "../shared/string-normalization.js"; import { sanitizeForLog } from "../terminal/ansi.js"; import { resolveUserPath } from "../utils.js"; @@ -169,90 +166,6 @@ const DEFAULT_MANIFEST_CACHE_MS = 1000; export { clearPluginManifestRegistryCache } from "./manifest-registry-state.js"; -function listContractValues( - plugin: PluginManifestRecord, - contract: PluginManifestContractListKey, -): readonly string[] { - return plugin.contracts?.[contract] ?? []; -} - -export function resolveManifestContractPluginIds(params: { - contract: PluginManifestContractListKey; - origin?: PluginOrigin; - config?: OpenClawConfig; - workspaceDir?: string; - env?: NodeJS.ProcessEnv; - onlyPluginIds?: readonly string[]; -}): string[] { - const onlyPluginIdSet = - params.onlyPluginIds && params.onlyPluginIds.length > 0 ? new Set(params.onlyPluginIds) : null; - return loadPluginManifestRegistry({ - config: params.config, - workspaceDir: params.workspaceDir, - env: params.env, - }) - .plugins.filter( - (plugin) => - (!params.origin || plugin.origin === params.origin) && - (!onlyPluginIdSet || onlyPluginIdSet.has(plugin.id)) && - listContractValues(plugin, params.contract).length > 0, - ) - .map((plugin) => plugin.id) - .toSorted((left, right) => left.localeCompare(right)); -} - -export function resolveManifestContractPluginIdsByCompatibilityRuntimePath(params: { - contract: PluginManifestContractListKey; - path: string | undefined; - origin?: PluginOrigin; - config?: OpenClawConfig; - workspaceDir?: string; - env?: NodeJS.ProcessEnv; -}): string[] { - const normalizedPath = params.path?.trim(); - if (!normalizedPath) { - return []; - } - return loadPluginManifestRegistry({ - config: params.config, - workspaceDir: params.workspaceDir, - env: params.env, - }) - .plugins.filter( - (plugin) => - (!params.origin || plugin.origin === params.origin) && - listContractValues(plugin, params.contract).length > 0 && - (plugin.configContracts?.compatibilityRuntimePaths ?? []).includes(normalizedPath), - ) - .map((plugin) => plugin.id) - .toSorted((left, right) => left.localeCompare(right)); -} - -export function resolveManifestContractOwnerPluginId(params: { - contract: PluginManifestContractListKey; - value: string | undefined; - origin?: PluginOrigin; - config?: OpenClawConfig; - workspaceDir?: string; - env?: NodeJS.ProcessEnv; -}): string | undefined { - const normalizedValue = normalizeOptionalLowercaseString(params.value); - if (!normalizedValue) { - return undefined; - } - return loadPluginManifestRegistry({ - config: params.config, - workspaceDir: params.workspaceDir, - env: params.env, - }).plugins.find( - (plugin) => - (!params.origin || plugin.origin === params.origin) && - listContractValues(plugin, params.contract).some( - (candidate) => normalizeOptionalLowercaseString(candidate) === normalizedValue, - ), - )?.id; -} - function resolveManifestCacheMs(env: NodeJS.ProcessEnv): number { const raw = env.OPENCLAW_PLUGIN_MANIFEST_CACHE_MS?.trim(); if (raw === "" || raw === "0") { diff --git a/src/plugins/providers.test.ts b/src/plugins/providers.test.ts index ab93185da1d..a34057ba930 100644 --- a/src/plugins/providers.test.ts +++ b/src/plugins/providers.test.ts @@ -10,8 +10,6 @@ type LoadOpenClawPlugins = typeof import("./loader.js").loadOpenClawPlugins; type IsPluginRegistryLoadInFlight = typeof import("./loader.js").isPluginRegistryLoadInFlight; type LoadPluginManifestRegistry = typeof import("./manifest-registry.js").loadPluginManifestRegistry; -type ResolveManifestContractPluginIds = - typeof import("./manifest-registry.js").resolveManifestContractPluginIds; type ApplyPluginAutoEnable = typeof import("../config/plugin-auto-enable.js").applyPluginAutoEnable; type SetActivePluginRegistry = typeof import("./runtime.js").setActivePluginRegistry; @@ -19,23 +17,6 @@ const resolveRuntimePluginRegistryMock = vi.fn(); const loadOpenClawPluginsMock = vi.fn(); const isPluginRegistryLoadInFlightMock = vi.fn((_) => false); const loadPluginManifestRegistryMock = vi.fn(); -const resolveManifestContractPluginIdsMock = vi.fn((params) => { - const onlyPluginIds = - params.onlyPluginIds && params.onlyPluginIds.length > 0 ? new Set(params.onlyPluginIds) : null; - return loadPluginManifestRegistryMock({ - config: params.config, - workspaceDir: params.workspaceDir, - env: params.env, - }) - .plugins.filter( - (plugin) => - (!params.origin || plugin.origin === params.origin) && - (!onlyPluginIds || onlyPluginIds.has(plugin.id)) && - (plugin.contracts?.[params.contract] ?? []).length > 0, - ) - .map((plugin) => plugin.id) - .toSorted((left, right) => left.localeCompare(right)); -}); const applyPluginAutoEnableMock = vi.fn(); let resolveOwningPluginIdsForProvider: typeof import("./providers.js").resolveOwningPluginIdsForProvider; @@ -308,8 +289,6 @@ describe("resolvePluginProviders", () => { vi.doMock("./manifest-registry.js", () => ({ loadPluginManifestRegistry: (...args: Parameters) => loadPluginManifestRegistryMock(...args), - resolveManifestContractPluginIds: (...args: Parameters) => - resolveManifestContractPluginIdsMock(...args), })); vi.doMock("./installed-plugin-index-store.js", async (importOriginal) => { const actual = await importOriginal(); @@ -355,7 +334,6 @@ describe("resolvePluginProviders", () => { resolveRuntimePluginRegistryMock.mockReturnValue(registry); loadOpenClawPluginsMock.mockReturnValue(registry); loadPluginManifestRegistryMock.mockReset(); - resolveManifestContractPluginIdsMock.mockClear(); applyPluginAutoEnableMock.mockReset(); applyPluginAutoEnableMock.mockImplementation( (params): PluginAutoEnableResult => ({ @@ -474,7 +452,6 @@ describe("resolvePluginProviders", () => { declaredPluginIds, }), ).toEqual(["legacy-auth-owner"]); - expect(resolveManifestContractPluginIdsMock).not.toHaveBeenCalled(); }); it("treats explicit empty provider scopes as scoped-empty in provider helpers", () => {