mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 14:20:44 +00:00
fix: reserve legacy tool cli token
This commit is contained in:
@@ -241,6 +241,10 @@ export const cliCommandCatalog: readonly CliCommandCatalogEntry[] = [
|
||||
},
|
||||
route: { id: "tasks-list" },
|
||||
},
|
||||
{
|
||||
commandPath: ["tool"],
|
||||
policy: { loadPlugins: "never", ensureCliPath: false, networkProxy: "bypass" },
|
||||
},
|
||||
{
|
||||
commandPath: ["tools"],
|
||||
policy: { loadPlugins: "never", ensureCliPath: false, networkProxy: "bypass" },
|
||||
|
||||
@@ -151,6 +151,9 @@ describe("command-path-policy", () => {
|
||||
expect(resolveCliNetworkProxyPolicy(["node", "openclaw", "googlemeet", "login"])).toBe(
|
||||
"default",
|
||||
);
|
||||
expect(resolveCliNetworkProxyPolicy(["node", "openclaw", "tool", "image_generate"])).toBe(
|
||||
"bypass",
|
||||
);
|
||||
expect(resolveCliNetworkProxyPolicy(["node", "openclaw", "tools", "effective"])).toBe("bypass");
|
||||
});
|
||||
|
||||
|
||||
@@ -50,6 +50,13 @@ describe("command-registration-policy", () => {
|
||||
hasBuiltinPrimary: false,
|
||||
}),
|
||||
).toBe(false);
|
||||
expect(
|
||||
shouldSkipPluginCommandRegistration({
|
||||
argv: ["node", "openclaw", "tool", "image_generate"],
|
||||
primary: "tool",
|
||||
hasBuiltinPrimary: false,
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
shouldSkipPluginCommandRegistration({
|
||||
argv: ["node", "openclaw", "tools", "effective"],
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { isTruthyEnvValue } from "../infra/env.js";
|
||||
import { resolveCliArgvInvocation } from "./argv-invocation.js";
|
||||
|
||||
const RESERVED_NON_PLUGIN_COMMAND_ROOTS = new Set(["tools"]);
|
||||
const RESERVED_NON_PLUGIN_COMMAND_ROOTS = new Set(["tool", "tools"]);
|
||||
|
||||
export function isReservedNonPluginCommandRoot(primary: string | null | undefined): boolean {
|
||||
return typeof primary === "string" && RESERVED_NON_PLUGIN_COMMAND_ROOTS.has(primary);
|
||||
}
|
||||
|
||||
export function shouldRegisterPrimaryCommandOnly(argv: string[]): boolean {
|
||||
const invocation = resolveCliArgvInvocation(argv);
|
||||
@@ -23,7 +27,7 @@ export function shouldSkipPluginCommandRegistration(params: {
|
||||
if (!params.primary) {
|
||||
return invocation.hasHelpOrVersion;
|
||||
}
|
||||
if (RESERVED_NON_PLUGIN_COMMAND_ROOTS.has(params.primary)) {
|
||||
if (isReservedNonPluginCommandRoot(params.primary)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
resolveCliCommandPathPolicy,
|
||||
resolveCliNetworkProxyPolicy,
|
||||
} from "./command-path-policy.js";
|
||||
import { isReservedNonPluginCommandRoot } from "./command-registration-policy.js";
|
||||
|
||||
const ROOT_HELP_ALIASES = new Set(["tools"]);
|
||||
|
||||
@@ -152,6 +153,10 @@ export function resolveMissingPluginCommandMessage(
|
||||
}
|
||||
}
|
||||
|
||||
if (isReservedNonPluginCommandRoot(normalizedPluginId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (allow.length > 0 && !allow.includes(normalizedPluginId)) {
|
||||
if (parentPluginId && allow.includes(parentPluginId)) {
|
||||
return null;
|
||||
|
||||
@@ -363,6 +363,7 @@ describe("runCli exit behavior", () => {
|
||||
["models list", ["node", "openclaw", "models", "list"]],
|
||||
["models status without live probe", ["node", "openclaw", "models", "status"]],
|
||||
["tasks list", ["node", "openclaw", "tasks", "list"]],
|
||||
["legacy singular tool namespace", ["node", "openclaw", "tool", "image_generate"]],
|
||||
["gateway tools namespace typo", ["node", "openclaw", "tools", "effective"]],
|
||||
["migrate", ["node", "openclaw", "migrate"]],
|
||||
])("skips managed proxy routing for %s", (_name, argv) => {
|
||||
@@ -385,24 +386,22 @@ describe("runCli exit behavior", () => {
|
||||
expect(startProxyMock).toHaveBeenCalledWith(undefined);
|
||||
});
|
||||
|
||||
it("keeps gateway tool RPC names out of plugin command discovery", async () => {
|
||||
it.each([
|
||||
["tool", ["node", "openclaw", "tool", "image_generate"]],
|
||||
["tools", ["node", "openclaw", "tools", "effective"]],
|
||||
])("keeps reserved %s command roots out of plugin command discovery", async (_name, argv) => {
|
||||
const parseAsync = vi.fn().mockResolvedValueOnce(undefined);
|
||||
buildProgramMock.mockReturnValueOnce({
|
||||
commands: [],
|
||||
parseAsync,
|
||||
});
|
||||
|
||||
await runCli(["node", "openclaw", "tools", "effective"]);
|
||||
await runCli(argv);
|
||||
|
||||
expect(startProxyMock).not.toHaveBeenCalled();
|
||||
expect(registerSubCliByNameMock).toHaveBeenCalledWith(expect.anything(), "tools", [
|
||||
"node",
|
||||
"openclaw",
|
||||
"tools",
|
||||
"effective",
|
||||
]);
|
||||
expect(registerSubCliByNameMock).toHaveBeenCalledWith(expect.anything(), argv[2], argv);
|
||||
expect(registerPluginCliCommandsFromValidatedConfigMock).not.toHaveBeenCalled();
|
||||
expect(parseAsync).toHaveBeenCalledWith(["node", "openclaw", "tools", "effective"]);
|
||||
expect(parseAsync).toHaveBeenCalledWith(argv);
|
||||
});
|
||||
|
||||
it("fails protected commands when managed proxy activation fails", async () => {
|
||||
|
||||
@@ -213,6 +213,15 @@ describe("resolveMissingPluginCommandMessage", () => {
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it("does not classify reserved non-plugin command roots as plugin allowlist misses", () => {
|
||||
const message = resolveMissingPluginCommandMessage("tool", {
|
||||
plugins: {
|
||||
allow: ["browser"],
|
||||
},
|
||||
});
|
||||
expect(message).toBeNull();
|
||||
});
|
||||
|
||||
it("explains that dreaming is a runtime slash command, not a CLI command", () => {
|
||||
const message = resolveMissingPluginCommandMessage(
|
||||
"dreaming",
|
||||
|
||||
Reference in New Issue
Block a user