fix: clear plugin discovery cache after plugin installation (openclaw#39752)

Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: GazeKingNuWu <264914544+GazeKingNuWu@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
This commit is contained in:
GazeKingNuWu
2026-03-09 13:16:25 +08:00
committed by GitHub
parent a40c29b11a
commit 41450187dd
4 changed files with 37 additions and 1 deletions

View File

@@ -24,6 +24,7 @@ Docs: https://docs.openclaw.ai
- Docker/runtime image: prune dev dependencies, strip build-only dist metadata for smaller Docker images. (#40307) Thanks @vincentkoc.
- Plugins/channel onboarding: prefer bundled channel plugins over duplicate npm-installed copies during onboarding and release-channel sync, preventing bundled plugins from being shadowed by npm installs with the same plugin ID. (#40092)
- Feishu/plugin onboarding: clear the short-lived plugin discovery cache before reloading the registry after installing a channel plugin, so onboarding no longer re-prompts to download Feishu immediately after a successful install. Fixes #39642. (#39752) Thanks @GazeKingNuWu.
- macOS app/chat UI: route browser proxy through the local node browser service, preserve plain-text paste semantics, strip completed assistant trace/debug wrapper noise from transcripts, refresh permission state after returning from System Settings, and tolerate malformed cron rows in the macOS tab. (#39516) Thanks @Imhermes1.
- Mattermost replies: keep `root_id` pinned to the existing thread root when an agent replies inside a thread, while still using reply-target threading for top-level posts. (#27744) thanks @hnykda.
- Agents/failover: detect Amazon Bedrock `Too many tokens per day` quota errors as rate limits across fallback, cron retry, and memory embeddings while keeping context-window `too many tokens per request` errors out of the rate-limit lane. (#39377) Thanks @gambletan.

View File

@@ -49,12 +49,21 @@ vi.mock("../../plugins/loader.js", () => ({
loadOpenClawPlugins: vi.fn(),
}));
const clearPluginDiscoveryCache = vi.fn();
vi.mock("../../plugins/discovery.js", () => ({
clearPluginDiscoveryCache: () => clearPluginDiscoveryCache(),
}));
import fs from "node:fs";
import type { ChannelPluginCatalogEntry } from "../../channels/plugins/catalog.js";
import type { OpenClawConfig } from "../../config/config.js";
import { loadOpenClawPlugins } from "../../plugins/loader.js";
import type { WizardPrompter } from "../../wizard/prompts.js";
import { makePrompter, makeRuntime } from "./__tests__/test-utils.js";
import { ensureOnboardingPluginInstalled } from "./plugin-install.js";
import {
ensureOnboardingPluginInstalled,
reloadOnboardingPluginRegistry,
} from "./plugin-install.js";
const baseEntry: ChannelPluginCatalogEntry = {
id: "zalo",
@@ -236,4 +245,27 @@ describe("ensureOnboardingPluginInstalled", () => {
expect(note).toHaveBeenCalled();
expect(runtime.error).not.toHaveBeenCalled();
});
it("clears discovery cache before reloading the onboarding plugin registry", () => {
const runtime = makeRuntime();
const cfg: OpenClawConfig = {};
reloadOnboardingPluginRegistry({
cfg,
runtime,
workspaceDir: "/tmp/openclaw-workspace",
});
expect(clearPluginDiscoveryCache).toHaveBeenCalledTimes(1);
expect(loadOpenClawPlugins).toHaveBeenCalledWith(
expect.objectContaining({
config: cfg,
workspaceDir: "/tmp/openclaw-workspace",
cache: false,
}),
);
expect(clearPluginDiscoveryCache.mock.invocationCallOrder[0]).toBeLessThan(
vi.mocked(loadOpenClawPlugins).mock.invocationCallOrder[0] ?? Number.POSITIVE_INFINITY,
);
});
});

View File

@@ -9,6 +9,7 @@ import {
findBundledPluginSourceInMap,
resolveBundledPluginSources,
} from "../../plugins/bundled-sources.js";
import { clearPluginDiscoveryCache } from "../../plugins/discovery.js";
import { enablePluginInConfig } from "../../plugins/enable.js";
import { installPluginFromNpmSpec } from "../../plugins/install.js";
import { buildNpmResolutionInstallFields, recordPluginInstall } from "../../plugins/installs.js";
@@ -224,6 +225,7 @@ export function reloadOnboardingPluginRegistry(params: {
runtime: RuntimeEnv;
workspaceDir?: string;
}): void {
clearPluginDiscoveryCache();
const workspaceDir =
params.workspaceDir ?? resolveAgentWorkspaceDir(params.cfg, resolveDefaultAgentId(params.cfg));
const log = createSubsystemLogger("plugins");

View File

@@ -64,6 +64,7 @@ vi.mock("../../agents/skills/refresh.js", () => ({
}));
vi.mock("../../agents/workspace.js", () => ({
DEFAULT_IDENTITY_FILENAME: "IDENTITY.md",
ensureAgentWorkspace: vi.fn().mockResolvedValue({ dir: "/tmp/workspace" }),
}));