mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-31 03:41:51 +00:00
refactor: centralize plugin install config policy
This commit is contained in:
@@ -50,6 +50,7 @@ describe("ensureConfigReady", () => {
|
||||
runtime: RuntimeEnv;
|
||||
commandPath?: string[];
|
||||
suppressDoctorStdout?: boolean;
|
||||
allowInvalid?: boolean;
|
||||
}) => Promise<void>;
|
||||
let resetConfigGuardStateForTests: () => void;
|
||||
|
||||
@@ -144,9 +145,14 @@ describe("ensureConfigReady", () => {
|
||||
expect(gatewayRuntime.exit).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not exit for invalid config on plugins install", async () => {
|
||||
it("allows an explicit invalid-config override", async () => {
|
||||
setInvalidSnapshot();
|
||||
const runtime = await runEnsureConfigReady(["plugins", "install"]);
|
||||
const runtime = makeRuntime();
|
||||
await ensureConfigReady({
|
||||
runtime: runtime as never,
|
||||
commandPath: ["plugins", "install"],
|
||||
allowInvalid: true,
|
||||
});
|
||||
expect(runtime.exit).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ const ALLOWED_INVALID_GATEWAY_SUBCOMMANDS = new Set([
|
||||
"stop",
|
||||
"restart",
|
||||
]);
|
||||
const ALLOWED_INVALID_PLUGINS_SUBCOMMANDS = new Set(["install"]);
|
||||
let didRunDoctorConfigFlow = false;
|
||||
let configSnapshotPromise: Promise<Awaited<ReturnType<typeof readConfigFileSnapshot>>> | null =
|
||||
null;
|
||||
@@ -38,6 +37,7 @@ export async function ensureConfigReady(params: {
|
||||
runtime: RuntimeEnv;
|
||||
commandPath?: string[];
|
||||
suppressDoctorStdout?: boolean;
|
||||
allowInvalid?: boolean;
|
||||
}): Promise<void> {
|
||||
const commandPath = params.commandPath ?? [];
|
||||
let preflightSnapshot: Awaited<ReturnType<typeof readConfigFileSnapshot>> | null = null;
|
||||
@@ -74,13 +74,11 @@ export async function ensureConfigReady(params: {
|
||||
const commandName = commandPath[0];
|
||||
const subcommandName = commandPath[1];
|
||||
const allowInvalid = commandName
|
||||
? ALLOWED_INVALID_COMMANDS.has(commandName) ||
|
||||
? params.allowInvalid === true ||
|
||||
ALLOWED_INVALID_COMMANDS.has(commandName) ||
|
||||
(commandName === "gateway" &&
|
||||
subcommandName &&
|
||||
ALLOWED_INVALID_GATEWAY_SUBCOMMANDS.has(subcommandName)) ||
|
||||
(commandName === "plugins" &&
|
||||
subcommandName &&
|
||||
ALLOWED_INVALID_PLUGINS_SUBCOMMANDS.has(subcommandName))
|
||||
ALLOWED_INVALID_GATEWAY_SUBCOMMANDS.has(subcommandName))
|
||||
: false;
|
||||
const { formatConfigIssueLines } = await import("../../config/issue-format.js");
|
||||
const issues =
|
||||
|
||||
@@ -129,6 +129,12 @@ describe("registerPreActionHooks", () => {
|
||||
program.command("onboard").action(() => {});
|
||||
const channels = program.command("channels");
|
||||
channels.command("add").action(() => {});
|
||||
program
|
||||
.command("plugins")
|
||||
.command("install")
|
||||
.argument("<spec>")
|
||||
.option("--marketplace <marketplace>")
|
||||
.action(() => {});
|
||||
program
|
||||
.command("update")
|
||||
.command("status")
|
||||
@@ -229,6 +235,61 @@ describe("registerPreActionHooks", () => {
|
||||
expect(ensurePluginRegistryLoadedMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("only allows invalid config for explicit Matrix reinstall requests", async () => {
|
||||
await runPreAction({
|
||||
parseArgv: ["plugins", "install", "@openclaw/matrix"],
|
||||
processArgv: ["node", "openclaw", "plugins", "install", "@openclaw/matrix"],
|
||||
});
|
||||
|
||||
expect(ensureConfigReadyMock).toHaveBeenCalledWith({
|
||||
runtime: runtimeMock,
|
||||
commandPath: ["plugins", "install"],
|
||||
allowInvalid: true,
|
||||
});
|
||||
|
||||
vi.clearAllMocks();
|
||||
await runPreAction({
|
||||
parseArgv: ["plugins", "install", "alpha"],
|
||||
processArgv: ["node", "openclaw", "plugins", "install", "alpha"],
|
||||
});
|
||||
|
||||
expect(ensureConfigReadyMock).toHaveBeenCalledWith({
|
||||
runtime: runtimeMock,
|
||||
commandPath: ["plugins", "install"],
|
||||
});
|
||||
|
||||
vi.clearAllMocks();
|
||||
await runPreAction({
|
||||
parseArgv: ["plugins", "install", "./extensions/matrix"],
|
||||
processArgv: ["node", "openclaw", "plugins", "install", "./extensions/matrix"],
|
||||
});
|
||||
|
||||
expect(ensureConfigReadyMock).toHaveBeenCalledWith({
|
||||
runtime: runtimeMock,
|
||||
commandPath: ["plugins", "install"],
|
||||
allowInvalid: true,
|
||||
});
|
||||
|
||||
vi.clearAllMocks();
|
||||
await runPreAction({
|
||||
parseArgv: ["plugins", "install", "@openclaw/matrix", "--marketplace", "local/repo"],
|
||||
processArgv: [
|
||||
"node",
|
||||
"openclaw",
|
||||
"plugins",
|
||||
"install",
|
||||
"@openclaw/matrix",
|
||||
"--marketplace",
|
||||
"local/repo",
|
||||
],
|
||||
});
|
||||
|
||||
expect(ensureConfigReadyMock).toHaveBeenCalledWith({
|
||||
runtime: runtimeMock,
|
||||
commandPath: ["plugins", "install"],
|
||||
});
|
||||
});
|
||||
|
||||
it("skips help/version preaction and respects banner opt-out", async () => {
|
||||
await runPreAction({
|
||||
parseArgv: ["status"],
|
||||
|
||||
@@ -8,6 +8,10 @@ import { defaultRuntime } from "../../runtime.js";
|
||||
import { getCommandPathWithRootOptions, getVerboseFlag, hasHelpOrVersion } from "../argv.js";
|
||||
import { emitCliBanner } from "../banner.js";
|
||||
import { resolveCliName } from "../cli-name.js";
|
||||
import {
|
||||
resolvePluginInstallInvalidConfigPolicy,
|
||||
resolvePluginInstallPreactionRequest,
|
||||
} from "../plugin-install-config-policy.js";
|
||||
import { isCommandJsonOutputMode } from "./json-mode.js";
|
||||
|
||||
function setProcessTitleForCommand(actionCommand: Command) {
|
||||
@@ -81,6 +85,18 @@ function shouldLoadPluginsForCommand(commandPath: string[], jsonOutputMode: bool
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function shouldAllowInvalidConfigForAction(actionCommand: Command, commandPath: string[]): boolean {
|
||||
return (
|
||||
resolvePluginInstallInvalidConfigPolicy(
|
||||
resolvePluginInstallPreactionRequest({
|
||||
actionCommand,
|
||||
commandPath,
|
||||
argv: process.argv,
|
||||
}),
|
||||
) === "recover-matrix-only"
|
||||
);
|
||||
}
|
||||
|
||||
function getRootCommand(command: Command): Command {
|
||||
let current = command;
|
||||
while (current.parent) {
|
||||
@@ -133,10 +149,12 @@ export function registerPreActionHooks(program: Command, programVersion: string)
|
||||
if (shouldBypassConfigGuard(commandPath)) {
|
||||
return;
|
||||
}
|
||||
const allowInvalid = shouldAllowInvalidConfigForAction(actionCommand, commandPath);
|
||||
const { ensureConfigReady } = await loadConfigGuardModule();
|
||||
await ensureConfigReady({
|
||||
runtime: defaultRuntime,
|
||||
commandPath,
|
||||
...(allowInvalid ? { allowInvalid: true } : {}),
|
||||
...(jsonOutputMode ? { suppressDoctorStdout: true } : {}),
|
||||
});
|
||||
// Load plugins for commands that need channel access.
|
||||
|
||||
Reference in New Issue
Block a user