From ead76f61d87e8e9aead1ccd59cd1855085a862bb Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 26 Apr 2026 19:05:26 -0700 Subject: [PATCH] fix(cli): skip plugin preload for plugin updates --- src/cli/program/register.subclis-core.ts | 11 ++++++-- src/cli/program/register.subclis.test.ts | 35 ++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/cli/program/register.subclis-core.ts b/src/cli/program/register.subclis-core.ts index 066b0410c02..80176ced24f 100644 --- a/src/cli/program/register.subclis-core.ts +++ b/src/cli/program/register.subclis-core.ts @@ -1,5 +1,6 @@ import type { Command } from "commander"; import { resolveCliArgvInvocation } from "../argv-invocation.js"; +import { resolveCliCommandPathPolicy } from "../command-path-policy.js"; import { shouldEagerRegisterSubcommands, shouldRegisterPrimarySubcommandOnly, @@ -30,13 +31,17 @@ async function registerSubCliWithPluginCommands( registerSubCli: () => Promise, pluginCliPosition: "before" | "after", ) { - const isHelpOrVersion = resolveCliArgvInvocation(process.argv).hasHelpOrVersion; + const invocation = resolveCliArgvInvocation(process.argv); + const shouldRegisterPluginCommands = + !invocation.hasHelpOrVersion && + (invocation.commandPath.length <= 1 || + resolveCliCommandPathPolicy(invocation.commandPath).loadPlugins !== "never"); const { registerPluginCliCommandsFromValidatedConfig } = await import("../../plugins/cli.js"); - if (pluginCliPosition === "before" && !isHelpOrVersion) { + if (pluginCliPosition === "before" && shouldRegisterPluginCommands) { await registerPluginCliCommandsFromValidatedConfig(program); } await registerSubCli(); - if (pluginCliPosition === "after" && !isHelpOrVersion) { + if (pluginCliPosition === "after" && shouldRegisterPluginCommands) { await registerPluginCliCommandsFromValidatedConfig(program); } } diff --git a/src/cli/program/register.subclis.test.ts b/src/cli/program/register.subclis.test.ts index 6720eb3424f..fd3b3053947 100644 --- a/src/cli/program/register.subclis.test.ts +++ b/src/cli/program/register.subclis.test.ts @@ -37,9 +37,22 @@ const { inferAction, registerCapabilityCli } = vi.hoisted(() => { return { inferAction: action, registerCapabilityCli: register }; }); +const { registerPluginsCli, registerPluginCliCommandsFromValidatedConfig } = vi.hoisted(() => ({ + registerPluginsCli: vi.fn((program: Command) => { + const plugins = program.command("plugins"); + plugins + .command("update") + .argument("[id]") + .action(() => undefined); + }), + registerPluginCliCommandsFromValidatedConfig: vi.fn(async () => null), +})); + vi.mock("../acp-cli.js", () => ({ registerAcpCli })); vi.mock("../nodes-cli.js", () => ({ registerNodesCli })); vi.mock("../capability-cli.js", () => ({ registerCapabilityCli })); +vi.mock("../plugins-cli.js", () => ({ registerPluginsCli })); +vi.mock("../../plugins/cli.js", () => ({ registerPluginCliCommandsFromValidatedConfig })); vi.mock("./private-qa-cli.js", async () => { const actual = await vi.importActual("./private-qa-cli.js"); return { @@ -78,6 +91,8 @@ describe("registerSubCliCommands", () => { loadPrivateQaCliModule.mockClear(); registerCapabilityCli.mockClear(); inferAction.mockClear(); + registerPluginsCli.mockClear(); + registerPluginCliCommandsFromValidatedConfig.mockClear(); }); afterEach(() => { @@ -158,4 +173,24 @@ describe("registerSubCliCommands", () => { expect(registerAcpCli).toHaveBeenCalledTimes(1); expect(acpAction).toHaveBeenCalledTimes(1); }); + + it("does not preload plugin CLI registrations for builtin plugins update", async () => { + process.argv = ["node", "openclaw", "plugins", "update", "lossless-claw"]; + const program = new Command().name("openclaw"); + + await registerSubCliByName(program, "plugins"); + + expect(registerPluginsCli).toHaveBeenCalledTimes(1); + expect(registerPluginCliCommandsFromValidatedConfig).not.toHaveBeenCalled(); + }); + + it("keeps plugin CLI registrations available for the plugins command root", async () => { + process.argv = ["node", "openclaw", "plugins"]; + const program = new Command().name("openclaw"); + + await registerSubCliByName(program, "plugins"); + + expect(registerPluginsCli).toHaveBeenCalledTimes(1); + expect(registerPluginCliCommandsFromValidatedConfig).toHaveBeenCalledTimes(1); + }); });