fix: explain disabled plugin command aliases

This commit is contained in:
Peter Steinberger
2026-05-03 18:07:51 +01:00
parent bd0e10a2f6
commit b3749a54e5
5 changed files with 70 additions and 1 deletions

View File

@@ -29,6 +29,7 @@ Docs: https://docs.openclaw.ai
### Fixes
- Gateway/update: recover an installed-but-unloaded macOS LaunchAgent after package updates, rerun Gateway health/version/channel readiness checks, and print restart, reinstall, and rollback guidance before reporting update failure. (#76790) Thanks @jonathanlindsay.
- CLI/plugins: explain when a missing plugin command alias belongs to a bundled plugin that is disabled by default, including the `openclaw plugins enable <plugin>` repair command. (#76835)
- Google Meet: route stateful CLI session commands through the gateway-owned runtime so joined realtime sessions survive after the starting CLI process exits. Fixes #76344. Thanks @coltonharris-wq.
- Memory/status: split builtin sqlite-vec store readiness from embedding-provider readiness in `memory status --deep` and `openclaw status`, so local vector-store failures no longer look like provider failures and provider failures no longer hide a healthy local vector store.
- CLI/doctor: trust a ready gateway memory probe when CLI-side active memory backend resolution is unavailable, preventing false "No active memory plugin is registered" warnings for healthy runtime setups. Fixes #76792. Thanks @som-686.

View File

@@ -141,6 +141,17 @@ export function resolveMissingPluginCommandMessage(
"the bundled plugin command surface."
);
}
if (
commandAlias.kind !== "runtime-slash" &&
commandAlias.enabledByDefault !== true &&
config?.plugins?.entries?.[parentPluginId]?.enabled !== true
) {
return (
`The \`openclaw ${normalizedPluginId}\` command is provided by the ` +
`"${parentPluginId}" plugin, but that bundled plugin is disabled by default. Run ` +
`\`openclaw plugins enable ${parentPluginId}\` to enable that CLI surface.`
);
}
if (commandAlias.kind === "runtime-slash") {
const cliHint = commandAlias.cliCommand
? `Use \`openclaw ${commandAlias.cliCommand}\` for related CLI operations, or `

View File

@@ -16,6 +16,7 @@ const memoryWikiCommandAliasRegistry: PluginManifestCommandAliasRegistry = {
plugins: [
{
id: "memory-wiki",
enabledByDefault: true,
commandAliases: [{ name: "wiki" }],
},
],
@@ -271,6 +272,54 @@ describe("resolveMissingPluginCommandMessage", () => {
expect(message).toContain("plugins.allow");
});
it("explains disabled-by-default parent plugins for CLI command aliases", () => {
const message = resolveMissingPluginCommandMessage(
"voicecall",
{},
{
registry: {
plugins: [
{
id: "voice-call",
commandAliases: [{ name: "voicecall" }],
},
],
},
},
);
expect(message).toContain('"voice-call" plugin');
expect(message).toContain("disabled by default");
expect(message).toContain("openclaw plugins enable voice-call");
});
it("returns null for CLI command aliases when disabled-by-default parent plugins are enabled", () => {
const message = resolveMissingPluginCommandMessage(
"voicecall",
{
plugins: {
entries: {
"voice-call": {
enabled: true,
},
},
},
},
{
registry: {
plugins: [
{
id: "voice-call",
commandAliases: [{ name: "voicecall" }],
},
],
},
},
);
expect(message).toBeNull();
});
it("explains parent plugin disablement for runtime command aliases", () => {
const message = resolveMissingPluginCommandMessage(
"dreaming",

View File

@@ -29,6 +29,7 @@ describe("manifest command aliases", () => {
},
{
id: "memory",
enabledByDefault: true,
commandAliases: [{ name: "legacy-memory" }],
},
],
@@ -41,6 +42,7 @@ describe("manifest command aliases", () => {
resolveManifestCommandAliasOwnerInRegistry({ command: "legacy-memory", registry }),
).toMatchObject({
pluginId: "memory",
enabledByDefault: true,
name: "legacy-memory",
});
});

View File

@@ -17,11 +17,13 @@ export type PluginManifestCommandAlias = {
export type PluginManifestCommandAliasRecord = PluginManifestCommandAlias & {
pluginId: string;
enabledByDefault?: boolean;
};
export type PluginManifestCommandAliasRegistry = {
plugins: readonly {
id: string;
enabledByDefault?: boolean;
commandAliases?: readonly PluginManifestCommandAlias[];
}[];
};
@@ -81,7 +83,11 @@ export function resolveManifestCommandAliasOwnerInRegistry(params: {
(entry) => normalizeOptionalLowercaseString(entry.name) === normalizedCommand,
);
if (alias) {
return { ...alias, pluginId: plugin.id };
return {
...alias,
pluginId: plugin.id,
...(plugin.enabledByDefault === true ? { enabledByDefault: true } : {}),
};
}
}
return undefined;