mirror of https://github.com/openclaw/openclaw.git
fix: tighten gateway startup plugin loading
This commit is contained in:
parent
1ca12ec8bf
commit
85611f0021
|
|
@ -24,6 +24,7 @@ type GatewayPluginBootstrapParams = {
|
|||
log: GatewayPluginBootstrapLog;
|
||||
coreGatewayHandlers: Record<string, GatewayRequestHandler>;
|
||||
baseMethods: string[];
|
||||
pluginIds?: string[];
|
||||
preferSetupRuntimeForChannelPlugins?: boolean;
|
||||
logDiagnostics?: boolean;
|
||||
beforePrimeRegistry?: (pluginRegistry: PluginRegistry) => void;
|
||||
|
|
@ -68,6 +69,7 @@ export function prepareGatewayPluginLoad(params: GatewayPluginBootstrapParams) {
|
|||
log: params.log,
|
||||
coreGatewayHandlers: params.coreGatewayHandlers,
|
||||
baseMethods: params.baseMethods,
|
||||
pluginIds: params.pluginIds,
|
||||
preferSetupRuntimeForChannelPlugins: params.preferSetupRuntimeForChannelPlugins,
|
||||
});
|
||||
params.beforePrimeRegistry?.(loaded.pluginRegistry);
|
||||
|
|
|
|||
|
|
@ -257,6 +257,21 @@ describe("loadGatewayPlugins", () => {
|
|||
);
|
||||
});
|
||||
|
||||
test("reuses the provided startup plugin scope without recomputing it", async () => {
|
||||
loadOpenClawPlugins.mockReturnValue(createRegistry([]));
|
||||
|
||||
loadGatewayPluginsForTest({
|
||||
pluginIds: ["browser"],
|
||||
});
|
||||
|
||||
expect(resolveGatewayStartupPluginIds).not.toHaveBeenCalled();
|
||||
expect(loadOpenClawPlugins).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
onlyPluginIds: ["browser"],
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test("loads gateway plugins from the auto-enabled config snapshot", async () => {
|
||||
const autoEnabledConfig = { channels: { slack: { enabled: true } }, autoEnabled: true };
|
||||
applyPluginAutoEnable.mockReturnValue({ config: autoEnabledConfig, changes: [] });
|
||||
|
|
@ -634,6 +649,28 @@ describe("loadGatewayPlugins", () => {
|
|||
expect(log.info).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("reuses the initial startup plugin scope during deferred reloads", async () => {
|
||||
const { reloadDeferredGatewayPlugins } = serverPluginBootstrapModule;
|
||||
loadOpenClawPlugins.mockReturnValue(createRegistry([]));
|
||||
|
||||
reloadDeferredGatewayPlugins({
|
||||
cfg: {},
|
||||
workspaceDir: "/tmp",
|
||||
log: createTestLog(),
|
||||
coreGatewayHandlers: {},
|
||||
baseMethods: [],
|
||||
pluginIds: ["discord"],
|
||||
logDiagnostics: false,
|
||||
});
|
||||
|
||||
expect(resolveGatewayStartupPluginIds).not.toHaveBeenCalled();
|
||||
expect(loadOpenClawPlugins).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
onlyPluginIds: ["discord"],
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test("runs registry hook before priming configured bindings", async () => {
|
||||
const { prepareGatewayPluginLoad } = serverPluginBootstrapModule;
|
||||
const order: string[] = [];
|
||||
|
|
|
|||
|
|
@ -389,20 +389,24 @@ export function loadGatewayPlugins(params: {
|
|||
};
|
||||
coreGatewayHandlers: Record<string, GatewayRequestHandler>;
|
||||
baseMethods: string[];
|
||||
pluginIds?: string[];
|
||||
preferSetupRuntimeForChannelPlugins?: boolean;
|
||||
}) {
|
||||
const resolvedConfig = applyPluginAutoEnable({
|
||||
config: params.cfg,
|
||||
env: process.env,
|
||||
}).config;
|
||||
const pluginRegistry = loadOpenClawPlugins({
|
||||
config: resolvedConfig,
|
||||
workspaceDir: params.workspaceDir,
|
||||
onlyPluginIds: resolveGatewayStartupPluginIds({
|
||||
const pluginIds =
|
||||
params.pluginIds ??
|
||||
resolveGatewayStartupPluginIds({
|
||||
config: resolvedConfig,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: process.env,
|
||||
}),
|
||||
});
|
||||
const pluginRegistry = loadOpenClawPlugins({
|
||||
config: resolvedConfig,
|
||||
workspaceDir: params.workspaceDir,
|
||||
onlyPluginIds: pluginIds,
|
||||
logger: {
|
||||
info: (msg) => params.log.info(msg),
|
||||
warn: (msg) => params.log.warn(msg),
|
||||
|
|
|
|||
|
|
@ -54,7 +54,10 @@ import { scheduleGatewayUpdateCheck } from "../infra/update-startup.js";
|
|||
import { startDiagnosticHeartbeat, stopDiagnosticHeartbeat } from "../logging/diagnostic.js";
|
||||
import { createSubsystemLogger, runtimeForLogger } from "../logging/subsystem.js";
|
||||
import { resolveBundledPluginInstallCommandHint } from "../plugins/bundled-sources.js";
|
||||
import { resolveConfiguredDeferredChannelPluginIds } from "../plugins/channel-plugin-ids.js";
|
||||
import {
|
||||
resolveConfiguredDeferredChannelPluginIds,
|
||||
resolveGatewayStartupPluginIds,
|
||||
} from "../plugins/channel-plugin-ids.js";
|
||||
import { getGlobalHookRunner, runGlobalGatewayStopSafely } from "../plugins/hook-runner-global.js";
|
||||
import { createEmptyPluginRegistry } from "../plugins/registry.js";
|
||||
import { setActivePluginRegistry } from "../plugins/runtime.js";
|
||||
|
|
@ -582,6 +585,13 @@ export async function startGatewayServer(
|
|||
workspaceDir: defaultWorkspaceDir,
|
||||
env: process.env,
|
||||
});
|
||||
const startupPluginIds = minimalTestGateway
|
||||
? []
|
||||
: resolveGatewayStartupPluginIds({
|
||||
config: gatewayPluginConfigAtStart,
|
||||
workspaceDir: defaultWorkspaceDir,
|
||||
env: process.env,
|
||||
});
|
||||
const baseMethods = listGatewayMethods();
|
||||
const emptyPluginRegistry = createEmptyPluginRegistry();
|
||||
let pluginRegistry = emptyPluginRegistry;
|
||||
|
|
@ -593,6 +603,7 @@ export async function startGatewayServer(
|
|||
log,
|
||||
coreGatewayHandlers,
|
||||
baseMethods,
|
||||
pluginIds: startupPluginIds,
|
||||
preferSetupRuntimeForChannelPlugins: deferredConfiguredChannelPluginIds.length > 0,
|
||||
}));
|
||||
} else {
|
||||
|
|
@ -1348,6 +1359,7 @@ export async function startGatewayServer(
|
|||
log,
|
||||
coreGatewayHandlers,
|
||||
baseMethods,
|
||||
pluginIds: startupPluginIds,
|
||||
logDiagnostics: false,
|
||||
}));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,30 +133,31 @@ describe("resolveGatewayStartupPluginIds", () => {
|
|||
|
||||
it.each([
|
||||
[
|
||||
"includes configured channels, explicit bundled sidecars, and enabled non-bundled sidecars",
|
||||
"includes configured channels and explicitly enabled bundled sidecars",
|
||||
createStartupConfig({
|
||||
enabledPluginIds: ["demo-bundled-sidecar"],
|
||||
modelId: "demo-cli/demo-model",
|
||||
}),
|
||||
[
|
||||
"demo-channel",
|
||||
"demo-default-on-sidecar",
|
||||
"demo-provider-plugin",
|
||||
"demo-bundled-sidecar",
|
||||
"demo-global-sidecar",
|
||||
],
|
||||
["demo-channel", "demo-provider-plugin", "demo-bundled-sidecar"],
|
||||
],
|
||||
[
|
||||
"includes bundled plugins with enabledByDefault: true",
|
||||
"skips bundled plugins with enabledByDefault: true until something references them",
|
||||
{} as OpenClawConfig,
|
||||
["demo-channel", "demo-default-on-sidecar", "demo-global-sidecar"],
|
||||
["demo-channel"],
|
||||
],
|
||||
[
|
||||
"auto-loads bundled plugins referenced by configured provider ids",
|
||||
createStartupConfig({
|
||||
providerIds: ["demo-provider"],
|
||||
}),
|
||||
["demo-channel", "demo-default-on-sidecar", "demo-provider-plugin", "demo-global-sidecar"],
|
||||
["demo-channel", "demo-provider-plugin"],
|
||||
],
|
||||
[
|
||||
"keeps non-bundled sidecars out of startup unless explicitly enabled",
|
||||
createStartupConfig({
|
||||
enabledPluginIds: ["demo-global-sidecar"],
|
||||
}),
|
||||
["demo-channel", "demo-global-sidecar"],
|
||||
],
|
||||
] as const)("%s", (_name, config, expected) => {
|
||||
expectStartupPluginIdsCase({ config, expected });
|
||||
|
|
|
|||
|
|
@ -331,14 +331,10 @@ export function resolveGatewayStartupPluginIds(params: {
|
|||
if (!enabled) {
|
||||
return false;
|
||||
}
|
||||
if (plugin.origin !== "bundled") {
|
||||
return true;
|
||||
}
|
||||
return (
|
||||
pluginsConfig.allow.includes(plugin.id) ||
|
||||
pluginsConfig.entries[plugin.id]?.enabled === true ||
|
||||
pluginsConfig.slots.memory === plugin.id ||
|
||||
plugin.enabledByDefault === true
|
||||
pluginsConfig.slots.memory === plugin.id
|
||||
);
|
||||
})
|
||||
.map((plugin) => plugin.id);
|
||||
|
|
|
|||
Loading…
Reference in New Issue