test(plugins): fast-path bundled setup web providers

This commit is contained in:
Vincent Koc
2026-04-17 13:30:55 -07:00
parent c0b8250f4f
commit afdbf48914
6 changed files with 44 additions and 25 deletions

View File

@@ -133,6 +133,18 @@ describe("resolvePluginWebFetchProviders", () => {
expect(loadOpenClawPluginsMock).toHaveBeenCalledTimes(1);
});
it("loads manifest-declared web-fetch providers in setup mode without the plugin loader", () => {
const providers = resolvePluginWebFetchProviders({
config: createFirecrawlAllowConfig(),
mode: "setup",
});
expect(providers.map((provider) => `${provider.pluginId}:${provider.id}`)).toEqual([
"firecrawl:firecrawl",
]);
expect(loadOpenClawPluginsMock).not.toHaveBeenCalled();
});
it("does not force a fresh snapshot load when the same web-provider load is already in flight", () => {
const inFlightSpy = vi
.spyOn(loaderModule, "isPluginRegistryLoadInFlight")

View File

@@ -6,6 +6,7 @@ import {
resolveBundledWebFetchResolutionConfig,
sortWebFetchProviders,
} from "./web-fetch-providers.shared.js";
import { resolveBundledWebFetchProvidersFromPublicArtifacts } from "./web-provider-public-artifacts.js";
import {
mapRegistryProviders,
resolveManifestDeclaredWebProviderCandidatePluginIds,
@@ -71,6 +72,7 @@ export function resolvePluginWebFetchProviders(params: {
resolveBundledResolutionConfig: resolveBundledWebFetchResolutionConfig,
resolveCandidatePluginIds: resolveWebFetchCandidatePluginIds,
mapRegistryProviders: mapRegistryWebFetchProviders,
resolveBundledPublicArtifactProviders: resolveBundledWebFetchProvidersFromPublicArtifacts,
});
}

View File

@@ -67,6 +67,13 @@ type ResolveWebProviderRuntimeDeps<TEntry> = {
registry: PluginRegistry;
onlyPluginIds?: readonly string[];
}) => TEntry[];
resolveBundledPublicArtifactProviders?: (params: {
config?: PluginLoadOptions["config"];
workspaceDir?: string;
env?: PluginLoadOptions["env"];
bundledAllowlistCompat?: boolean;
onlyPluginIds?: readonly string[];
}) => TEntry[] | null;
};
export function createWebProviderSnapshotCache<TEntry>(): WebProviderSnapshotCache<TEntry> {
@@ -132,6 +139,18 @@ export function resolvePluginWebProviders<TEntry>(
if (pluginIds.length === 0) {
return [];
}
if (params.activate !== true) {
const bundledArtifactProviders = deps.resolveBundledPublicArtifactProviders?.({
config: params.config,
workspaceDir,
env,
bundledAllowlistCompat: params.bundledAllowlistCompat,
onlyPluginIds: pluginIds,
});
if (bundledArtifactProviders) {
return bundledArtifactProviders;
}
}
const registry = loadOpenClawPlugins(
buildPluginRuntimeLoadOptionsFromValues(
{

View File

@@ -401,19 +401,7 @@ describe("resolvePluginWebSearchProviders", () => {
});
expect(toRuntimeProviderKeys(providers)).toEqual(["brave:brave"]);
expect(loadOpenClawPluginsMock).toHaveBeenCalledWith(
expect.objectContaining({
onlyPluginIds: ["brave"],
config: expect.objectContaining({
plugins: expect.objectContaining({
allow: ["perplexity", "brave"],
entries: {
brave: { enabled: true },
},
}),
}),
}),
);
expect(loadOpenClawPluginsMock).not.toHaveBeenCalled();
});
it("loads plugin web-search providers from the auto-enabled config snapshot", () => {

View File

@@ -2,6 +2,7 @@ import { loadOpenClawPlugins } from "./loader.js";
import type { PluginLoadOptions } from "./loader.js";
import { type PluginManifestRecord } from "./manifest-registry.js";
import type { PluginWebSearchProviderEntry } from "./types.js";
import { resolveBundledWebSearchProvidersFromPublicArtifacts } from "./web-provider-public-artifacts.js";
import {
mapRegistryProviders,
resolveManifestDeclaredWebProviderCandidatePluginIds,
@@ -71,6 +72,7 @@ export function resolvePluginWebSearchProviders(params: {
resolveBundledResolutionConfig: resolveBundledWebSearchResolutionConfig,
resolveCandidatePluginIds: resolveWebSearchCandidatePluginIds,
mapRegistryProviders: mapRegistryWebSearchProviders,
resolveBundledPublicArtifactProviders: resolveBundledWebSearchProvidersFromPublicArtifacts,
});
}

View File

@@ -1,6 +1,5 @@
import { describe, expect, it } from "vitest";
import type { OpenClawConfig } from "../../../src/config/config.js";
import { loadBundledCapabilityRuntimeRegistry } from "../../../src/plugins/bundled-capability-runtime.js";
import { resolveManifestContractOwnerPluginId } from "../../../src/plugins/manifest-registry.js";
import { resolveBundledExplicitWebSearchProvidersFromPublicArtifacts } from "../../../src/plugins/web-provider-public-artifacts.explicit.js";
import { resolvePluginWebSearchProviders } from "../../../src/plugins/web-search-providers.runtime.js";
@@ -95,21 +94,18 @@ export function describeBundledWebSearchFastPathContract(pluginId: string) {
}
});
it("keeps fast-path provider metadata aligned with the bundled runtime registry", async () => {
it("keeps fast-path provider metadata aligned with bundled public artifacts", async () => {
const fastPathProviders = resolvePluginWebSearchProviders({
origin: "bundled",
onlyPluginIds: [pluginId],
mode: "setup",
}).filter((provider) => provider.pluginId === pluginId);
const pluginSdkResolution = process.env.VITEST ? "src" : "dist";
const bundledProviderEntries = loadBundledCapabilityRuntimeRegistry({
pluginIds: [pluginId],
pluginSdkResolution,
})
.webSearchProviders.filter((entry) => entry.pluginId === pluginId)
.map((entry) => ({
pluginId: entry.pluginId,
...entry.provider,
}));
const bundledProviderEntries =
resolveBundledExplicitWebSearchProvidersFromPublicArtifacts({
onlyPluginIds: [pluginId],
})?.filter((entry) => entry.pluginId === pluginId) ?? [];
expect(bundledProviderEntries.length).toBeGreaterThan(0);
expect(
sortComparableEntries(