fix(regression): scope channel setup reloads by channel registry

This commit is contained in:
Tak Hoffman
2026-03-27 22:46:02 -05:00
parent ec6fba7d01
commit f4f492a410
2 changed files with 41 additions and 3 deletions

View File

@@ -64,7 +64,11 @@ import type { ChannelPluginCatalogEntry } from "../../channels/plugins/catalog.j
import type { OpenClawConfig } from "../../config/config.js";
import { loadOpenClawPlugins } from "../../plugins/loader.js";
import { createEmptyPluginRegistry } from "../../plugins/registry.js";
import { setActivePluginRegistry } from "../../plugins/runtime.js";
import {
pinActivePluginChannelRegistry,
releasePinnedPluginChannelRegistry,
setActivePluginRegistry,
} from "../../plugins/runtime.js";
import { createPluginRecord } from "../../plugins/status.test-helpers.js";
import type { WizardPrompter } from "../../wizard/prompts.js";
import { makePrompter, makeRuntime } from "../setup/__tests__/test-utils.js";
@@ -448,6 +452,40 @@ describe("ensureChannelSetupPluginInstalled", () => {
);
});
it("scopes channel reloads when the global registry is populated but the pinned channel registry is empty", () => {
const runtime = makeRuntime();
const cfg: OpenClawConfig = {};
const activeRegistry = createEmptyPluginRegistry();
activeRegistry.plugins.push(
createPluginRecord({
id: "loaded-tools",
name: "loaded-tools",
source: "/tmp/loaded-tools.cjs",
origin: "bundled",
}),
);
setActivePluginRegistry(activeRegistry);
const pinnedChannelRegistry = createEmptyPluginRegistry();
pinActivePluginChannelRegistry(pinnedChannelRegistry);
try {
reloadChannelSetupPluginRegistryForChannel({
cfg,
runtime,
channel: "telegram",
workspaceDir: "/tmp/openclaw-workspace",
});
} finally {
releasePinnedPluginChannelRegistry(pinnedChannelRegistry);
}
expect(loadOpenClawPlugins).toHaveBeenCalledWith(
expect.objectContaining({
onlyPluginIds: ["telegram"],
}),
);
});
it("can load a channel-scoped snapshot without activating the global registry", () => {
const runtime = makeRuntime();
const cfg: OpenClawConfig = {};

View File

@@ -17,7 +17,7 @@ import { buildNpmResolutionInstallFields, recordPluginInstall } from "../../plug
import { loadOpenClawPlugins } from "../../plugins/loader.js";
import { createPluginLoaderLogger } from "../../plugins/logger.js";
import type { PluginRegistry } from "../../plugins/registry.js";
import { getActivePluginRegistry } from "../../plugins/runtime.js";
import { getActivePluginChannelRegistry } from "../../plugins/runtime.js";
import type { RuntimeEnv } from "../../runtime.js";
import type { WizardPrompter } from "../../wizard/prompts.js";
@@ -265,7 +265,7 @@ export function reloadChannelSetupPluginRegistryForChannel(params: {
pluginId?: string;
workspaceDir?: string;
}): void {
const activeRegistry = getActivePluginRegistry();
const activeRegistry = getActivePluginChannelRegistry();
// On low-memory hosts, the empty-registry fallback should only recover the selected
// plugin instead of importing every bundled extension during setup.
const onlyPluginIds = activeRegistry?.plugins.length