fix: propagate workspaceDir to snapshot plugin loads (#61138)

* plugins: include resolved workspaceDir in provider hook cache keys

resolveProviderPluginsForHooks, resolveProviderPluginsForCatalogHooks, and
resolveProviderRuntimePlugin used the raw params.workspaceDir for cache keys
and plugin-id discovery while resolvePluginProviders already fell back to
the active registry workspace. Resolve workspaceDir once at the top of each
function so cache keys, candidate filtering, and loading all use the same
workspace root.

* fix(plugins): inherit runtime workspace for snapshot loads

* test(gateway): stub runtime registry seam

* fix(plugins): restore workspace fallback after rebase

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
Jamil Zakirov
2026-04-05 11:03:54 +03:00
committed by GitHub
parent e28e83f4e4
commit ffb5b99114
13 changed files with 304 additions and 27 deletions

View File

@@ -89,12 +89,14 @@ type ServerPluginBootstrapModule = typeof import("./server-plugin-bootstrap.js")
type PluginRuntimeModule = typeof import("../plugins/runtime/index.js");
type GatewayRequestScopeModule = typeof import("../plugins/runtime/gateway-request-scope.js");
type MethodScopesModule = typeof import("./method-scopes.js");
type RuntimeStateModule = typeof import("../plugins/runtime-state.js");
let serverPluginsModule: ServerPluginsModule;
let serverPluginBootstrapModule: ServerPluginBootstrapModule;
let runtimeModule: PluginRuntimeModule;
let gatewayRequestScopeModule: GatewayRequestScopeModule;
let methodScopesModule: MethodScopesModule;
let getActivePluginRegistryWorkspaceDirFromState: typeof import("../plugins/runtime-state.js").getActivePluginRegistryWorkspaceDirFromState;
function createTestLog() {
return {
@@ -131,6 +133,8 @@ async function loadTestModules() {
runtimeModule = await import("../plugins/runtime/index.js");
gatewayRequestScopeModule = await import("../plugins/runtime/gateway-request-scope.js");
methodScopesModule = await import("./method-scopes.js");
const runtimeStateModule: RuntimeStateModule = await import("../plugins/runtime-state.js");
({ getActivePluginRegistryWorkspaceDirFromState } = runtimeStateModule);
}
async function createSubagentRuntime(
@@ -337,6 +341,20 @@ describe("loadGatewayPlugins", () => {
expect(result.gatewayMethods).toEqual(["sessions.get"]);
});
test("stores workspaceDir on the active registry when startup scope is empty", () => {
resolveGatewayStartupPluginIds.mockReturnValue([]);
serverPluginsModule.loadGatewayPlugins({
cfg: {},
workspaceDir: "/tmp/gateway-workspace",
log: createTestLog(),
coreGatewayHandlers: {},
baseMethods: [],
});
expect(getActivePluginRegistryWorkspaceDirFromState()).toBe("/tmp/gateway-workspace");
});
test("loads gateway plugins from the auto-enabled config snapshot", async () => {
const autoEnabledConfig = { channels: { slack: { enabled: true } }, autoEnabled: true };
applyPluginAutoEnable.mockReturnValue({

View File

@@ -429,7 +429,7 @@ export function loadGatewayPlugins(params: {
});
if (pluginIds.length === 0) {
const pluginRegistry = createEmptyPluginRegistry();
setActivePluginRegistry(pluginRegistry, undefined, "gateway-bindable");
setActivePluginRegistry(pluginRegistry, undefined, "gateway-bindable", params.workspaceDir);
return {
pluginRegistry,
gatewayMethods: [...params.baseMethods],

View File

@@ -945,8 +945,9 @@ function activatePluginRegistry(
registry: PluginRegistry,
cacheKey: string,
runtimeSubagentMode: "default" | "explicit" | "gateway-bindable",
workspaceDir?: string,
): void {
setActivePluginRegistry(registry, cacheKey, runtimeSubagentMode);
setActivePluginRegistry(registry, cacheKey, runtimeSubagentMode, workspaceDir);
initializeGlobalHookRunner(registry);
}
@@ -986,7 +987,12 @@ export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegi
runtime: cached.memoryRuntime,
});
if (shouldActivate) {
activatePluginRegistry(cached.registry, cacheKey, runtimeSubagentMode);
activatePluginRegistry(
cached.registry,
cacheKey,
runtimeSubagentMode,
options.workspaceDir,
);
}
return cached.registry;
}
@@ -1623,7 +1629,7 @@ export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegi
});
}
if (shouldActivate) {
activatePluginRegistry(registry, cacheKey, runtimeSubagentMode);
activatePluginRegistry(registry, cacheKey, runtimeSubagentMode, options.workspaceDir);
}
return registry;
}

View File

@@ -8,6 +8,7 @@ import {
} from "./providers.js";
import { resolvePluginProviders } from "./providers.runtime.js";
import { resolvePluginCacheInputs } from "./roots.js";
import { getActivePluginRegistryWorkspaceDirFromState } from "./runtime-state.js";
import type {
ProviderAuthDoctorHintContext,
ProviderAugmentModelCatalogContext,
@@ -134,13 +135,14 @@ function resolveProviderPluginsForHooks(params: {
onlyPluginIds?: string[];
}): ProviderPlugin[] {
const env = params.env ?? process.env;
const workspaceDir = params.workspaceDir ?? getActivePluginRegistryWorkspaceDirFromState();
const cacheBucket = resolveHookProviderCacheBucket({
config: params.config,
env,
});
const cacheKey = buildHookProviderCacheKey({
config: params.config,
workspaceDir: params.workspaceDir,
workspaceDir,
onlyPluginIds: params.onlyPluginIds,
env,
});
@@ -150,6 +152,7 @@ function resolveProviderPluginsForHooks(params: {
}
const resolved = resolvePluginProviders({
...params,
workspaceDir,
env,
activate: false,
cache: false,
@@ -165,9 +168,10 @@ function resolveProviderPluginsForCatalogHooks(params: {
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
}): ProviderPlugin[] {
const workspaceDir = params.workspaceDir ?? getActivePluginRegistryWorkspaceDirFromState();
const onlyPluginIds = resolveCatalogHookProviderPluginIds({
config: params.config,
workspaceDir: params.workspaceDir,
workspaceDir,
env: params.env,
});
if (onlyPluginIds.length === 0) {
@@ -175,6 +179,7 @@ function resolveProviderPluginsForCatalogHooks(params: {
}
return resolveProviderPluginsForHooks({
...params,
workspaceDir,
onlyPluginIds,
});
}
@@ -185,10 +190,11 @@ export function resolveProviderRuntimePlugin(params: {
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
}): ProviderPlugin | undefined {
const workspaceDir = params.workspaceDir ?? getActivePluginRegistryWorkspaceDirFromState();
const owningPluginIds = resolveOwningPluginIdsForProvider({
provider: params.provider,
config: params.config,
workspaceDir: params.workspaceDir,
workspaceDir,
env: params.env,
});
if (!owningPluginIds || owningPluginIds.length === 0) {
@@ -196,6 +202,7 @@ export function resolveProviderRuntimePlugin(params: {
}
return resolveProviderPluginsForHooks({
...params,
workspaceDir,
onlyPluginIds: owningPluginIds,
}).find((plugin) => matchesProviderId(plugin, params.provider));
}

View File

@@ -14,6 +14,7 @@ import {
resolveOwningPluginIdsForModelRefs,
withBundledProviderVitestCompat,
} from "./providers.js";
import { getActivePluginRegistryWorkspaceDir } from "./runtime.js";
import type { ProviderPlugin } from "./types.js";
const log = createSubsystemLogger("plugins");
@@ -33,11 +34,12 @@ export function resolvePluginProviders(params: {
mode?: "runtime" | "setup";
}): ProviderPlugin[] {
const env = params.env ?? process.env;
const workspaceDir = params.workspaceDir ?? getActivePluginRegistryWorkspaceDir();
const modelOwnedPluginIds = params.modelRefs?.length
? resolveOwningPluginIdsForModelRefs({
models: params.modelRefs,
config: params.config,
workspaceDir: params.workspaceDir,
workspaceDir,
env,
})
: [];
@@ -52,7 +54,7 @@ export function resolvePluginProviders(params: {
if (params.mode === "setup") {
const providerPluginIds = resolveDiscoveredProviderPluginIds({
config: runtimeConfig,
workspaceDir: params.workspaceDir,
workspaceDir,
env,
onlyPluginIds: requestedPluginIds,
});
@@ -66,7 +68,7 @@ export function resolvePluginProviders(params: {
}),
activationSourceConfig: runtimeConfig,
autoEnabledReasons: {},
workspaceDir: params.workspaceDir,
workspaceDir,
env,
onlyPluginIds: providerPluginIds,
pluginSdkResolution: params.pluginSdkResolution,
@@ -82,7 +84,7 @@ export function resolvePluginProviders(params: {
const activation = resolveBundledPluginCompatibleActivationInputs({
rawConfig: runtimeConfig,
env,
workspaceDir: params.workspaceDir,
workspaceDir,
onlyPluginIds: requestedPluginIds,
applyAutoEnable: true,
compatMode: {
@@ -101,7 +103,7 @@ export function resolvePluginProviders(params: {
: activation.config;
const providerPluginIds = resolveEnabledProviderPluginIds({
config,
workspaceDir: params.workspaceDir,
workspaceDir,
env,
onlyPluginIds: requestedPluginIds,
});
@@ -109,7 +111,7 @@ export function resolvePluginProviders(params: {
config,
activationSourceConfig: activation.activationSourceConfig,
autoEnabledReasons: activation.autoEnabledReasons,
workspaceDir: params.workspaceDir,
workspaceDir,
env,
onlyPluginIds: providerPluginIds,
pluginSdkResolution: params.pluginSdkResolution,

View File

@@ -10,6 +10,7 @@ type LoadOpenClawPlugins = typeof import("./loader.js").loadOpenClawPlugins;
type LoadPluginManifestRegistry =
typeof import("./manifest-registry.js").loadPluginManifestRegistry;
type ApplyPluginAutoEnable = typeof import("../config/plugin-auto-enable.js").applyPluginAutoEnable;
type SetActivePluginRegistry = typeof import("./runtime.js").setActivePluginRegistry;
const resolveRuntimePluginRegistryMock = vi.fn<ResolveRuntimePluginRegistry>();
const loadOpenClawPluginsMock = vi.fn<LoadOpenClawPlugins>();
@@ -20,6 +21,7 @@ let resolveOwningPluginIdsForProvider: typeof import("./providers.js").resolveOw
let resolveOwningPluginIdsForModelRef: typeof import("./providers.js").resolveOwningPluginIdsForModelRef;
let resolveEnabledProviderPluginIds: typeof import("./providers.js").resolveEnabledProviderPluginIds;
let resolvePluginProviders: typeof import("./providers.runtime.js").resolvePluginProviders;
let setActivePluginRegistry: SetActivePluginRegistry;
function createManifestProviderPlugin(params: {
id: string;
@@ -270,9 +272,11 @@ describe("resolvePluginProviders", () => {
resolveEnabledProviderPluginIds,
} = await import("./providers.js"));
({ resolvePluginProviders } = await import("./providers.runtime.js"));
({ setActivePluginRegistry } = await import("./runtime.js"));
});
beforeEach(() => {
setActivePluginRegistry(createEmptyPluginRegistry());
resolveRuntimePluginRegistryMock.mockReset();
loadOpenClawPluginsMock.mockReset();
const provider: ProviderPlugin = {
@@ -560,6 +564,32 @@ describe("resolvePluginProviders", () => {
);
});
it("inherits workspaceDir from the active registry when provider resolution omits it", () => {
setActivePluginRegistry(
createEmptyPluginRegistry(),
undefined,
"default",
"/workspace/runtime",
);
resolvePluginProviders({
config: {
plugins: {
allow: ["google"],
},
},
onlyPluginIds: ["google"],
});
expect(resolveRuntimePluginRegistryMock).toHaveBeenCalledWith(
expect.objectContaining({
workspaceDir: "/workspace/runtime",
cache: false,
activate: false,
}),
);
});
it.each([
{
provider: "minimax-portal",

View File

@@ -30,3 +30,8 @@ export function getActivePluginChannelRegistryFromState(): PluginRegistry | null
const state = getPluginRegistryState();
return state?.channel.registry ?? state?.activeRegistry ?? null;
}
export function getActivePluginRegistryWorkspaceDirFromState(): string | undefined {
const state = getPluginRegistryState();
return state?.workspaceDir ?? undefined;
}

View File

@@ -25,6 +25,7 @@ const state: RegistryState = (() => {
version: 0,
},
key: null,
workspaceDir: null,
runtimeSubagentMode: "default",
importedPluginIds: new Set<string>(),
};
@@ -70,12 +71,14 @@ export function setActivePluginRegistry(
registry: PluginRegistry,
cacheKey?: string,
runtimeSubagentMode: "default" | "explicit" | "gateway-bindable" = "default",
workspaceDir?: string,
) {
state.activeRegistry = registry;
state.activeVersion += 1;
syncTrackedSurface(state.httpRoute, registry, true);
syncTrackedSurface(state.channel, registry, true);
state.key = cacheKey ?? null;
state.workspaceDir = workspaceDir ?? null;
state.runtimeSubagentMode = runtimeSubagentMode;
}
@@ -83,6 +86,10 @@ export function getActivePluginRegistry(): PluginRegistry | null {
return state.activeRegistry;
}
export function getActivePluginRegistryWorkspaceDir(): string | undefined {
return state.workspaceDir ?? undefined;
}
export function requireActivePluginRegistry(): PluginRegistry {
if (!state.activeRegistry) {
state.activeRegistry = createEmptyPluginRegistry();
@@ -222,6 +229,7 @@ export function resetPluginRuntimeStateForTest(): void {
installSurfaceRegistry(state.httpRoute, null, false);
installSurfaceRegistry(state.channel, null, false);
state.key = null;
state.workspaceDir = null;
state.runtimeSubagentMode = "default";
state.importedPluginIds.clear();
}

View File

@@ -168,4 +168,91 @@ describe("resolvePluginWebFetchProviders", () => {
]);
expect(loadOpenClawPluginsMock).not.toHaveBeenCalled();
});
it("inherits workspaceDir from the active registry for compatible web-fetch snapshot reuse", () => {
const env = createWebFetchEnv();
const rawConfig = createFirecrawlAllowConfig();
const { config, activationSourceConfig, autoEnabledReasons } =
webFetchProvidersSharedModule.resolveBundledWebFetchResolutionConfig({
config: rawConfig,
bundledAllowlistCompat: true,
workspaceDir: DEFAULT_WORKSPACE,
env,
});
const { cacheKey } = loaderModule.__testing.resolvePluginLoadCacheContext({
config,
activationSourceConfig,
autoEnabledReasons,
workspaceDir: DEFAULT_WORKSPACE,
env,
onlyPluginIds: ["firecrawl"],
cache: false,
activate: false,
});
const registry = createEmptyPluginRegistry();
registry.webFetchProviders.push(createRuntimeWebFetchProvider());
setActivePluginRegistry(registry, cacheKey, "default", DEFAULT_WORKSPACE);
const providers = resolvePluginWebFetchProviders({
config: rawConfig,
bundledAllowlistCompat: true,
env,
});
expect(providers.map((provider) => `${provider.pluginId}:${provider.id}`)).toEqual([
"firecrawl:firecrawl",
]);
expect(loadOpenClawPluginsMock).not.toHaveBeenCalled();
});
it("uses the active registry workspace for candidate discovery and snapshot loads when workspaceDir is omitted", () => {
const env = createWebFetchEnv();
const rawConfig = createFirecrawlAllowConfig();
setActivePluginRegistry(
createEmptyPluginRegistry(),
undefined,
"default",
"/tmp/runtime-workspace",
);
resolvePluginWebFetchProviders({
config: rawConfig,
bundledAllowlistCompat: true,
env,
});
expect(manifestRegistryModule.loadPluginManifestRegistry).toHaveBeenCalledWith(
expect.objectContaining({
workspaceDir: "/tmp/runtime-workspace",
}),
);
expect(loadOpenClawPluginsMock).toHaveBeenCalledWith(
expect.objectContaining({
workspaceDir: "/tmp/runtime-workspace",
onlyPluginIds: ["firecrawl"],
}),
);
});
it("invalidates web-fetch snapshot memoization when the active registry workspace changes", () => {
const env = createWebFetchEnv();
const config = createFirecrawlAllowConfig();
setActivePluginRegistry(createEmptyPluginRegistry(), undefined, "default", "/tmp/workspace-a");
resolvePluginWebFetchProviders({
config,
bundledAllowlistCompat: true,
env,
});
setActivePluginRegistry(createEmptyPluginRegistry(), undefined, "default", "/tmp/workspace-b");
resolvePluginWebFetchProviders({
config,
bundledAllowlistCompat: true,
env,
});
expect(loadOpenClawPluginsMock).toHaveBeenCalledTimes(2);
});
});

View File

@@ -19,6 +19,7 @@ import {
resolveManifestContractPluginIds,
type PluginManifestRecord,
} from "./manifest-registry.js";
import { getActivePluginRegistryWorkspaceDir } from "./runtime.js";
import type { PluginWebFetchProviderEntry } from "./types.js";
import {
resolveBundledWebFetchResolutionConfig,
@@ -127,14 +128,16 @@ function resolveWebFetchLoadOptions(params: {
origin?: PluginManifestRecord["origin"];
}) {
const env = params.env ?? process.env;
const workspaceDir = params.workspaceDir ?? getActivePluginRegistryWorkspaceDir();
const { config, activationSourceConfig, autoEnabledReasons } =
resolveBundledWebFetchResolutionConfig({
...params,
workspaceDir,
env,
});
const onlyPluginIds = resolveWebFetchCandidatePluginIds({
config,
workspaceDir: params.workspaceDir,
workspaceDir,
env,
onlyPluginIds: params.onlyPluginIds,
origin: params.origin,
@@ -144,7 +147,7 @@ function resolveWebFetchLoadOptions(params: {
config,
activationSourceConfig,
autoEnabledReasons,
workspaceDir: params.workspaceDir,
workspaceDir,
cache: params.cache ?? false,
activate: params.activate ?? false,
...(onlyPluginIds ? { onlyPluginIds } : {}),
@@ -180,11 +183,12 @@ export function resolvePluginWebFetchProviders(params: {
origin?: PluginManifestRecord["origin"];
}): PluginWebFetchProviderEntry[] {
const env = params.env ?? process.env;
const workspaceDir = params.workspaceDir ?? getActivePluginRegistryWorkspaceDir();
if (params.mode === "setup") {
const pluginIds =
resolveWebFetchCandidatePluginIds({
config: params.config,
workspaceDir: params.workspaceDir,
workspaceDir,
env,
onlyPluginIds: params.onlyPluginIds,
origin: params.origin,
@@ -199,7 +203,7 @@ export function resolvePluginWebFetchProviders(params: {
}),
activationSourceConfig: params.config,
autoEnabledReasons: {},
workspaceDir: params.workspaceDir,
workspaceDir,
env,
onlyPluginIds: pluginIds,
cache: params.cache ?? false,
@@ -213,7 +217,7 @@ export function resolvePluginWebFetchProviders(params: {
params.activate !== true && params.cache !== true && shouldUsePluginSnapshotCache(env);
const cacheKey = buildWebFetchSnapshotCacheKey({
config: cacheOwnerConfig,
workspaceDir: params.workspaceDir,
workspaceDir,
bundledAllowlistCompat: params.bundledAllowlistCompat,
onlyPluginIds: params.onlyPluginIds,
origin: params.origin,
@@ -227,7 +231,7 @@ export function resolvePluginWebFetchProviders(params: {
return cached.providers;
}
}
const loadOptions = resolveWebFetchLoadOptions(params);
const loadOptions = resolveWebFetchLoadOptions({ ...params, workspaceDir });
// Keep repeated runtime reads on the already-compatible active registry when
// possible, then fall back to a fresh snapshot load only when necessary.
const resolved = mapRegistryWebFetchProviders({
@@ -266,7 +270,12 @@ export function resolveRuntimeWebFetchProviders(params: {
origin?: PluginManifestRecord["origin"];
}): PluginWebFetchProviderEntry[] {
const runtimeRegistry = resolveRuntimePluginRegistry(
params.config === undefined ? undefined : resolveWebFetchLoadOptions(params),
params.config === undefined
? undefined
: resolveWebFetchLoadOptions({
...params,
workspaceDir: params.workspaceDir ?? getActivePluginRegistryWorkspaceDir(),
}),
);
if (runtimeRegistry) {
return mapRegistryWebFetchProviders({

View File

@@ -398,6 +398,35 @@ describe("resolvePluginWebSearchProviders", () => {
expectScopedWebSearchCandidates(["brave"]);
});
it("uses the active registry workspace for candidate discovery and snapshot loads when workspaceDir is omitted", () => {
const env = createWebSearchEnv();
const rawConfig = createBraveAllowConfig();
setActivePluginRegistry(
createEmptyPluginRegistry(),
undefined,
"default",
"/tmp/runtime-workspace",
);
resolvePluginWebSearchProviders({
config: rawConfig,
bundledAllowlistCompat: true,
env,
});
expect(loadPluginManifestRegistryMock).toHaveBeenCalledWith(
expect.objectContaining({
workspaceDir: "/tmp/runtime-workspace",
}),
);
expect(loadOpenClawPluginsMock).toHaveBeenCalledWith(
expect.objectContaining({
workspaceDir: "/tmp/runtime-workspace",
onlyPluginIds: ["brave"],
}),
);
});
it("memoizes snapshot provider resolution for the same config and env", () => {
expectSnapshotMemoization({
config: createBraveAllowConfig(),
@@ -451,6 +480,72 @@ describe("resolvePluginWebSearchProviders", () => {
expect(loadOpenClawPluginsMock).not.toHaveBeenCalled();
});
it("inherits workspaceDir from the active registry for compatible web-search snapshot reuse", () => {
const env = createWebSearchEnv();
const rawConfig = createBraveAllowConfig();
const { config, activationSourceConfig, autoEnabledReasons } =
webSearchProvidersSharedModule.resolveBundledWebSearchResolutionConfig({
config: rawConfig,
bundledAllowlistCompat: true,
workspaceDir: DEFAULT_WEB_SEARCH_WORKSPACE,
env,
});
const { cacheKey } = loaderModule.__testing.resolvePluginLoadCacheContext({
config,
activationSourceConfig,
autoEnabledReasons,
workspaceDir: DEFAULT_WEB_SEARCH_WORKSPACE,
env,
onlyPluginIds: ["brave"],
cache: false,
activate: false,
});
const registry = createEmptyPluginRegistry();
registry.webSearchProviders.push(
createRuntimeWebSearchProvider({
pluginId: "brave",
pluginName: "Brave",
id: "brave",
label: "Brave Search",
hint: "Brave runtime provider",
envVar: "BRAVE_API_KEY",
signupUrl: "https://example.com/brave",
credentialPath: "plugins.entries.brave.config.webSearch.apiKey",
}),
);
setActivePluginRegistry(registry, cacheKey, "default", DEFAULT_WEB_SEARCH_WORKSPACE);
const providers = resolvePluginWebSearchProviders({
config: rawConfig,
bundledAllowlistCompat: true,
env,
});
expectRuntimeProviderResolution(providers, ["brave:brave"]);
expect(loadOpenClawPluginsMock).not.toHaveBeenCalled();
});
it("keys web-search snapshot memoization by the inherited active workspace", () => {
const env = createWebSearchEnv();
const rawConfig = createBraveAllowConfig();
setActivePluginRegistry(createEmptyPluginRegistry(), undefined, "default", "/tmp/workspace-a");
resolvePluginWebSearchProviders({
config: rawConfig,
bundledAllowlistCompat: true,
env,
});
setActivePluginRegistry(createEmptyPluginRegistry(), undefined, "default", "/tmp/workspace-b");
resolvePluginWebSearchProviders({
config: rawConfig,
bundledAllowlistCompat: true,
env,
});
expectLoaderCallCount(2);
});
it.each([
{
name: "invalidates the snapshot cache when config contents change in place",

View File

@@ -19,6 +19,7 @@ import {
resolveManifestContractPluginIds,
type PluginManifestRecord,
} from "./manifest-registry.js";
import { getActivePluginRegistryWorkspaceDir } from "./runtime.js";
import type { PluginWebSearchProviderEntry } from "./types.js";
import {
resolveBundledWebSearchResolutionConfig,
@@ -126,14 +127,16 @@ function resolveWebSearchLoadOptions(params: {
origin?: PluginManifestRecord["origin"];
}) {
const env = params.env ?? process.env;
const workspaceDir = params.workspaceDir ?? getActivePluginRegistryWorkspaceDir();
const { config, activationSourceConfig, autoEnabledReasons } =
resolveBundledWebSearchResolutionConfig({
...params,
workspaceDir,
env,
});
const onlyPluginIds = resolveWebSearchCandidatePluginIds({
config,
workspaceDir: params.workspaceDir,
workspaceDir,
env,
onlyPluginIds: params.onlyPluginIds,
origin: params.origin,
@@ -143,7 +146,7 @@ function resolveWebSearchLoadOptions(params: {
config,
activationSourceConfig,
autoEnabledReasons,
workspaceDir: params.workspaceDir,
workspaceDir,
cache: params.cache ?? false,
activate: params.activate ?? false,
...(onlyPluginIds ? { onlyPluginIds } : {}),
@@ -179,11 +182,12 @@ export function resolvePluginWebSearchProviders(params: {
origin?: PluginManifestRecord["origin"];
}): PluginWebSearchProviderEntry[] {
const env = params.env ?? process.env;
const workspaceDir = params.workspaceDir ?? getActivePluginRegistryWorkspaceDir();
if (params.mode === "setup") {
const pluginIds =
resolveWebSearchCandidatePluginIds({
config: params.config,
workspaceDir: params.workspaceDir,
workspaceDir,
env,
onlyPluginIds: params.onlyPluginIds,
origin: params.origin,
@@ -198,7 +202,7 @@ export function resolvePluginWebSearchProviders(params: {
}),
activationSourceConfig: params.config,
autoEnabledReasons: {},
workspaceDir: params.workspaceDir,
workspaceDir,
env,
onlyPluginIds: pluginIds,
cache: params.cache ?? false,
@@ -212,7 +216,7 @@ export function resolvePluginWebSearchProviders(params: {
params.activate !== true && params.cache !== true && shouldUsePluginSnapshotCache(env);
const cacheKey = buildWebSearchSnapshotCacheKey({
config: cacheOwnerConfig,
workspaceDir: params.workspaceDir,
workspaceDir,
bundledAllowlistCompat: params.bundledAllowlistCompat,
onlyPluginIds: params.onlyPluginIds,
origin: params.origin,
@@ -226,7 +230,7 @@ export function resolvePluginWebSearchProviders(params: {
return cached.providers;
}
}
const loadOptions = resolveWebSearchLoadOptions(params);
const loadOptions = resolveWebSearchLoadOptions({ ...params, workspaceDir });
// Prefer the compatible active registry so repeated runtime reads do not
// re-import the same plugin set through the snapshot path.
const resolved = mapRegistryWebSearchProviders({
@@ -265,7 +269,12 @@ export function resolveRuntimeWebSearchProviders(params: {
origin?: PluginManifestRecord["origin"];
}): PluginWebSearchProviderEntry[] {
const runtimeRegistry = resolveRuntimePluginRegistry(
params.config === undefined ? undefined : resolveWebSearchLoadOptions(params),
params.config === undefined
? undefined
: resolveWebSearchLoadOptions({
...params,
workspaceDir: params.workspaceDir ?? getActivePluginRegistryWorkspaceDir(),
}),
);
if (runtimeRegistry) {
return mapRegistryWebSearchProviders({