mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-20 21:23:23 +00:00
Plugins: reuse compatible runtime web search registries
This commit is contained in:
@@ -5,6 +5,7 @@ type RuntimeModule = typeof import("./runtime.js");
|
||||
type WebSearchProvidersRuntimeModule = typeof import("./web-search-providers.runtime.js");
|
||||
type ManifestRegistryModule = typeof import("./manifest-registry.js");
|
||||
type PluginAutoEnableModule = typeof import("../config/plugin-auto-enable.js");
|
||||
type WebSearchProvidersSharedModule = typeof import("./web-search-providers.shared.js");
|
||||
|
||||
const BUNDLED_WEB_SEARCH_PROVIDERS = [
|
||||
{ pluginId: "brave", id: "brave", order: 10 },
|
||||
@@ -29,6 +30,7 @@ let loaderModule: typeof import("./loader.js");
|
||||
let manifestRegistryModule: ManifestRegistryModule;
|
||||
let pluginAutoEnableModule: PluginAutoEnableModule;
|
||||
let applyPluginAutoEnableSpy: ReturnType<typeof vi.fn>;
|
||||
let webSearchProvidersSharedModule: WebSearchProvidersSharedModule;
|
||||
|
||||
const DEFAULT_WEB_SEARCH_WORKSPACE = "/tmp/workspace";
|
||||
const EXPECTED_BUNDLED_RUNTIME_WEB_SEARCH_PROVIDER_KEYS = [
|
||||
@@ -206,6 +208,7 @@ describe("resolvePluginWebSearchProviders", () => {
|
||||
manifestRegistryModule = await import("./manifest-registry.js");
|
||||
loaderModule = await import("./loader.js");
|
||||
pluginAutoEnableModule = await import("../config/plugin-auto-enable.js");
|
||||
webSearchProvidersSharedModule = await import("./web-search-providers.shared.js");
|
||||
({ setActivePluginRegistry } = await import("./runtime.js"));
|
||||
({
|
||||
resolvePluginWebSearchProviders,
|
||||
@@ -417,4 +420,55 @@ describe("resolvePluginWebSearchProviders", () => {
|
||||
expect(toRuntimeProviderKeys(providers)).toEqual(["custom-search:custom"]);
|
||||
expect(loadOpenClawPluginsMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("reuses a compatible active registry for runtime resolution when config is provided", () => {
|
||||
const env = createWebSearchEnv();
|
||||
const { config } = webSearchProvidersSharedModule.resolveBundledWebSearchResolutionConfig({
|
||||
config: createBraveAllowConfig(),
|
||||
bundledAllowlistCompat: true,
|
||||
env,
|
||||
});
|
||||
const { cacheKey } = loaderModule.resolvePluginLoadCacheContext({
|
||||
config,
|
||||
workspaceDir: DEFAULT_WEB_SEARCH_WORKSPACE,
|
||||
env,
|
||||
onlyPluginIds: ["brave"],
|
||||
cache: false,
|
||||
activate: false,
|
||||
});
|
||||
const registry = createEmptyPluginRegistry();
|
||||
registry.webSearchProviders.push({
|
||||
pluginId: "brave",
|
||||
pluginName: "Brave",
|
||||
provider: {
|
||||
id: "brave",
|
||||
label: "Brave Search",
|
||||
hint: "Brave runtime provider",
|
||||
envVars: ["BRAVE_API_KEY"],
|
||||
placeholder: "brave-...",
|
||||
signupUrl: "https://example.com/brave",
|
||||
autoDetectOrder: 1,
|
||||
credentialPath: "tools.web.search.brave.apiKey",
|
||||
getCredentialValue: () => "configured",
|
||||
setCredentialValue: () => {},
|
||||
createTool: () => ({
|
||||
description: "brave",
|
||||
parameters: {},
|
||||
execute: async () => ({}),
|
||||
}),
|
||||
},
|
||||
source: "test",
|
||||
});
|
||||
setActivePluginRegistry(registry, cacheKey);
|
||||
|
||||
const providers = resolveRuntimeWebSearchProviders({
|
||||
config: createBraveAllowConfig(),
|
||||
bundledAllowlistCompat: true,
|
||||
workspaceDir: DEFAULT_WEB_SEARCH_WORKSPACE,
|
||||
env,
|
||||
});
|
||||
|
||||
expect(toRuntimeProviderKeys(providers)).toEqual(["brave:brave"]);
|
||||
expect(loadOpenClawPluginsMock).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,11 +6,10 @@ import {
|
||||
resolvePluginSnapshotCacheTtlMs,
|
||||
shouldUsePluginSnapshotCache,
|
||||
} from "./cache-controls.js";
|
||||
import { loadOpenClawPlugins } from "./loader.js";
|
||||
import { getCompatibleActivePluginRegistry, loadOpenClawPlugins } from "./loader.js";
|
||||
import type { PluginLoadOptions } from "./loader.js";
|
||||
import { createPluginLoaderLogger } from "./logger.js";
|
||||
import { loadPluginManifestRegistry, type PluginManifestRecord } from "./manifest-registry.js";
|
||||
import { getActivePluginRegistry } from "./runtime.js";
|
||||
import type { PluginWebSearchProviderEntry } from "./types.js";
|
||||
import {
|
||||
resolveBundledWebSearchResolutionConfig,
|
||||
@@ -94,6 +93,53 @@ function resolveWebSearchCandidatePluginIds(params: {
|
||||
return ids.length > 0 ? ids : undefined;
|
||||
}
|
||||
|
||||
function resolveWebSearchLoadOptions(params: {
|
||||
config?: PluginLoadOptions["config"];
|
||||
workspaceDir?: string;
|
||||
env?: PluginLoadOptions["env"];
|
||||
bundledAllowlistCompat?: boolean;
|
||||
onlyPluginIds?: readonly string[];
|
||||
activate?: boolean;
|
||||
cache?: boolean;
|
||||
}) {
|
||||
const env = params.env ?? process.env;
|
||||
const { config } = resolveBundledWebSearchResolutionConfig({
|
||||
...params,
|
||||
env,
|
||||
});
|
||||
const onlyPluginIds = resolveWebSearchCandidatePluginIds({
|
||||
config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env,
|
||||
onlyPluginIds: params.onlyPluginIds,
|
||||
});
|
||||
return {
|
||||
env,
|
||||
config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
cache: params.cache ?? false,
|
||||
activate: params.activate ?? false,
|
||||
...(onlyPluginIds ? { onlyPluginIds } : {}),
|
||||
logger: createPluginLoaderLogger(log),
|
||||
} satisfies PluginLoadOptions;
|
||||
}
|
||||
|
||||
function mapRegistryWebSearchProviders(params: {
|
||||
registry: ReturnType<typeof loadOpenClawPlugins>;
|
||||
onlyPluginIds?: readonly string[];
|
||||
}): PluginWebSearchProviderEntry[] {
|
||||
const onlyPluginIdSet =
|
||||
params.onlyPluginIds && params.onlyPluginIds.length > 0 ? new Set(params.onlyPluginIds) : null;
|
||||
return sortWebSearchProviders(
|
||||
params.registry.webSearchProviders
|
||||
.filter((entry) => !onlyPluginIdSet || onlyPluginIdSet.has(entry.pluginId))
|
||||
.map((entry) => ({
|
||||
...entry.provider,
|
||||
pluginId: entry.pluginId,
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
export function resolvePluginWebSearchProviders(params: {
|
||||
config?: PluginLoadOptions["config"];
|
||||
workspaceDir?: string;
|
||||
@@ -122,32 +168,10 @@ export function resolvePluginWebSearchProviders(params: {
|
||||
return cached.providers;
|
||||
}
|
||||
}
|
||||
const { config } = resolveBundledWebSearchResolutionConfig({
|
||||
...params,
|
||||
env,
|
||||
const loadOptions = resolveWebSearchLoadOptions(params);
|
||||
const resolved = mapRegistryWebSearchProviders({
|
||||
registry: loadOpenClawPlugins(loadOptions),
|
||||
});
|
||||
const onlyPluginIds = resolveWebSearchCandidatePluginIds({
|
||||
config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env,
|
||||
onlyPluginIds: params.onlyPluginIds,
|
||||
});
|
||||
const registry = loadOpenClawPlugins({
|
||||
config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env,
|
||||
cache: params.cache ?? false,
|
||||
activate: params.activate ?? false,
|
||||
...(onlyPluginIds ? { onlyPluginIds } : {}),
|
||||
logger: createPluginLoaderLogger(log),
|
||||
});
|
||||
|
||||
const resolved = sortWebSearchProviders(
|
||||
registry.webSearchProviders.map((entry) => ({
|
||||
...entry.provider,
|
||||
pluginId: entry.pluginId,
|
||||
})),
|
||||
);
|
||||
if (cacheOwnerConfig && shouldMemoizeSnapshot) {
|
||||
const ttlMs = resolvePluginSnapshotCacheTtlMs(env);
|
||||
let configCache = webSearchProviderSnapshotCache.get(cacheOwnerConfig);
|
||||
@@ -178,18 +202,15 @@ export function resolveRuntimeWebSearchProviders(params: {
|
||||
bundledAllowlistCompat?: boolean;
|
||||
onlyPluginIds?: readonly string[];
|
||||
}): PluginWebSearchProviderEntry[] {
|
||||
const runtimeProviders = getActivePluginRegistry()?.webSearchProviders ?? [];
|
||||
const onlyPluginIdSet =
|
||||
params.onlyPluginIds && params.onlyPluginIds.length > 0 ? new Set(params.onlyPluginIds) : null;
|
||||
if (runtimeProviders.length > 0) {
|
||||
return sortWebSearchProviders(
|
||||
runtimeProviders
|
||||
.filter((entry) => !onlyPluginIdSet || onlyPluginIdSet.has(entry.pluginId))
|
||||
.map((entry) => ({
|
||||
...entry.provider,
|
||||
pluginId: entry.pluginId,
|
||||
})),
|
||||
);
|
||||
const runtimeRegistry =
|
||||
params.config === undefined
|
||||
? getCompatibleActivePluginRegistry()
|
||||
: getCompatibleActivePluginRegistry(resolveWebSearchLoadOptions(params));
|
||||
if (runtimeRegistry) {
|
||||
return mapRegistryWebSearchProviders({
|
||||
registry: runtimeRegistry,
|
||||
onlyPluginIds: params.onlyPluginIds,
|
||||
});
|
||||
}
|
||||
return resolvePluginWebSearchProviders(params);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user