mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-30 00:28:42 +00:00
fix(cli): reject unknown command help roots (#81083) (thanks @YB0y)
Behavior addressed: Unknown CLI command roots now error consistently even when --help or --version is appended, while legitimate built-in help fast paths still render normally. Real environment tested: Local OpenClaw source checkout plus GitHub workflow run-level status. Exact steps or command run after this patch: pnpm test src/cli/run-main.exit.test.ts src/cli/argv.test.ts src/cli/argv-invocation.test.ts; pnpm exec oxfmt --check --threads=1 src/cli/run-main.ts src/cli/run-main.exit.test.ts; autoreview --mode branch --base origin/main --no-web-search. Evidence after fix: Focused CLI test shards passed 178 tests; formatter clean; autoreview reported no accepted/actionable findings; GitHub CI run 26422344121 and CodeQL Critical Quality run 26422344090 completed successfully. Observed result after fix: `openclaw foo --help` and `openclaw foo --version` reject before proxy/program startup, while known help fast paths remain ahead of the unknown-root guard. What was not tested: Full local build; contributor PR body already supplied build/CLI command proof before rebase. Co-authored-by: YB0y <brianandez6@gmail.com>
This commit is contained in:
@@ -672,6 +672,26 @@ describe("runCli exit behavior", () => {
|
||||
expect(registerPluginCliCommandsFromValidatedConfigMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects unowned command roots even when --help is appended (regression for #81077)", async () => {
|
||||
await expect(runCli(["node", "openclaw", "foo", "--help"])).rejects.toThrow(
|
||||
'No built-in command or plugin CLI metadata owns "foo"',
|
||||
);
|
||||
|
||||
expect(startProxyMock).not.toHaveBeenCalled();
|
||||
expect(tryRouteCliMock).not.toHaveBeenCalled();
|
||||
expect(buildProgramMock).not.toHaveBeenCalled();
|
||||
expect(registerPluginCliCommandsFromValidatedConfigMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects unowned command roots even when --version is appended", async () => {
|
||||
await expect(runCli(["node", "openclaw", "foo", "--version"])).rejects.toThrow(
|
||||
'No built-in command or plugin CLI metadata owns "foo"',
|
||||
);
|
||||
|
||||
expect(startProxyMock).not.toHaveBeenCalled();
|
||||
expect(tryRouteCliMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not suggest plugins.allow for unknown command roots before proxy startup", async () => {
|
||||
loadConfigMock.mockReturnValueOnce({
|
||||
plugins: {
|
||||
|
||||
@@ -397,7 +397,6 @@ async function resolveUnownedCliPrimary(params: {
|
||||
const invocation = resolveCliArgvInvocation(rewriteUpdateFlagArgv(params.argv));
|
||||
const { primary } = invocation;
|
||||
if (
|
||||
invocation.hasHelpOrVersion ||
|
||||
!primary ||
|
||||
primary === "help" ||
|
||||
isReservedNonPluginCommandRoot(primary) ||
|
||||
@@ -616,6 +615,19 @@ export async function runCli(argv: string[] = process.argv) {
|
||||
}
|
||||
}
|
||||
|
||||
// Reject unowned command roots before help/version routing, so that
|
||||
// `openclaw <typo> --help` surfaces the same Unknown command error as
|
||||
// `openclaw <typo>` instead of silently showing generic top-level help.
|
||||
// Runs after legitimate precomputed help fast paths so known help commands
|
||||
// still dispatch normally. See #81077.
|
||||
{
|
||||
const config = await readBestEffortCliConfig();
|
||||
const unownedPrimary = await resolveUnownedCliPrimary({ argv: normalizedArgv, config });
|
||||
if (unownedPrimary) {
|
||||
throw new Error(await resolveUnownedCliPrimaryMessage({ primary: unownedPrimary, config }));
|
||||
}
|
||||
}
|
||||
|
||||
const shouldRunBareRootCrestodian = shouldStartCrestodianForBareRoot(normalizedArgv);
|
||||
const shouldRunModernOnboardCrestodian = shouldStartCrestodianForModernOnboard(normalizedArgv);
|
||||
if (shouldRunBareRootCrestodian || shouldRunModernOnboardCrestodian) {
|
||||
|
||||
Reference in New Issue
Block a user