fix: reuse lookup table for deferred plugin reload

This commit is contained in:
Shakker
2026-04-27 07:57:15 +01:00
parent e068165036
commit bed76c26e7
5 changed files with 20 additions and 0 deletions

View File

@@ -21,6 +21,7 @@ Docs: https://docs.openclaw.ai
- LM Studio: allow interactive onboarding to leave the API key blank for unauthenticated local servers, using local synthetic auth while clearing stale LM Studio auth profiles. Fixes #66937. Thanks @olamedia.
- Plugins/startup: use a `PluginLookUpTable` during Gateway startup so channel ownership, deferred channel loading, and startup plugin IDs reuse the same installed manifest registry instead of rebuilding manifest metadata on the boot path. Thanks @shakkernerd.
- Plugins/startup: pass the Gateway `PluginLookUpTable` through plugin loading so auto-enable checks and startup-scope fallback reuse the same manifest registry instead of doing another manifest pass. Thanks @shakkernerd.
- Plugins/startup: carry the Gateway `PluginLookUpTable` into deferred channel full-runtime reloads so post-listen startup does not rebuild manifest metadata after the provisional setup-runtime load. Thanks @shakkernerd.
- Plugins/registry: resolve lookup-table owner maps for providers, CLI backends, setup providers, command aliases, model catalogs, channel configs, and manifest contracts while preserving setup-only CLI backend ownership. Thanks @shakkernerd.
- Process/Windows: decode command stdout and stderr from raw bytes with console-codepage awareness, while preserving valid UTF-8 output and multibyte characters split across chunks. Fixes #50519. Thanks @iready, @kevinten10, @zhangyongjie1997, @knightplat-blip, @heiqishi666, and @slepybear.
- Agents/bootstrap: dedupe hook-injected bootstrap context files by workspace-relative path and store normalized resolved paths so duplicate relative and absolute hook paths no longer depend on the process cwd. (#59344; fixes #59319; related #56721, #56725, and #57587) Thanks @koen666.

View File

@@ -1052,6 +1052,7 @@ describe("loadGatewayPlugins", () => {
test("reuses the initial startup plugin scope during deferred reloads", async () => {
const { reloadDeferredGatewayPlugins } = serverPluginBootstrapModule;
loadOpenClawPlugins.mockReturnValue(createRegistry([]));
const manifestRegistry = { plugins: [], diagnostics: [] };
reloadDeferredGatewayPlugins({
cfg: {},
@@ -1060,10 +1061,19 @@ describe("loadGatewayPlugins", () => {
coreGatewayHandlers: {},
baseMethods: [],
pluginIds: ["discord"],
pluginLookUpTable: createLookUpTableForTest({
manifestRegistry,
pluginIds: ["discord"],
}),
logDiagnostics: false,
});
expect(loadPluginLookUpTable).not.toHaveBeenCalled();
expect(applyPluginAutoEnable).toHaveBeenCalledWith({
config: {},
env: process.env,
manifestRegistry,
});
expect(loadOpenClawPlugins).toHaveBeenCalledWith(
expect.objectContaining({
onlyPluginIds: ["discord"],

View File

@@ -151,6 +151,9 @@ describe("prepareGatewayPluginBootstrap runtime-deps staging", () => {
).resolves.toMatchObject({
baseGatewayMethods: ["ping"],
startupPluginIds: ["telegram"],
pluginLookUpTable: expect.objectContaining({
manifestRegistry: pluginManifestRegistry,
}),
});
expect(loadGatewayStartupPlugins).toHaveBeenCalledOnce();
@@ -194,6 +197,9 @@ describe("prepareGatewayPluginBootstrap runtime-deps staging", () => {
).resolves.toMatchObject({
baseGatewayMethods: ["ping"],
startupPluginIds: ["telegram"],
pluginLookUpTable: expect.objectContaining({
manifestRegistry: pluginManifestRegistry,
}),
});
expect(repairBundledRuntimeDepsInstallRootAsync).not.toHaveBeenCalled();

View File

@@ -182,6 +182,7 @@ export async function prepareGatewayPluginBootstrap(params: {
defaultWorkspaceDir,
deferredConfiguredChannelPluginIds,
startupPluginIds,
pluginLookUpTable,
baseMethods,
pluginRegistry,
baseGatewayMethods,

View File

@@ -378,6 +378,7 @@ export async function startGatewayServer(
defaultWorkspaceDir,
deferredConfiguredChannelPluginIds,
startupPluginIds,
pluginLookUpTable,
baseMethods,
} = pluginBootstrap;
let { pluginRegistry, baseGatewayMethods } = pluginBootstrap;
@@ -804,6 +805,7 @@ export async function startGatewayServer(
coreGatewayMethodNames: baseMethods,
baseMethods,
pluginIds: startupPluginIds,
pluginLookUpTable,
logDiagnostics: false,
}));
runtimeState.gatewayMethods = listActiveGatewayMethods(baseGatewayMethods);