fix(plugins): explain disabled CLI command roots

This commit is contained in:
Vincent Koc
2026-05-10 14:21:42 +08:00
parent 89960cfcc9
commit 0eb6848c7c
6 changed files with 28 additions and 6 deletions

View File

@@ -45,6 +45,7 @@ Docs: https://docs.openclaw.ai
- CLI/secrets: turn offline Gateway reload failures into actionable recovery text.
- CLI/channels: explain missing or ambiguous channel selections with next commands.
- CLI/channels: defer guided channel status collection until a channel is selected, keeping `openclaw channels add` first screen quieter.
- Plugins/CLI: route disabled Matrix and LanceDB memory command roots to plugin-enable guidance instead of generic unknown-command errors.
- Browser/Docker: detect Playwright-managed Chromium from `PLAYWRIGHT_BROWSERS_PATH` and the default Playwright cache on Linux, so Docker installs that persist `/home/node/.cache/ms-playwright` no longer need `browser.executablePath`.
- Ollama: keep DeepSeek V4 cloud models thinking-capable even when Ollama Cloud `/api/show` omits the `thinking` capability, so `/think high` no longer rejects `ollama/deepseek-v4-*:cloud`.
- ACPX/Claude ACP: keep foreground prompts waiting for their own result when autonomous task-notification results arrive during the same session, and retarget the patch for Claude Agent ACP `0.33.1`.

View File

@@ -1,7 +1,9 @@
{
"id": "matrix",
"commandAliases": [{ "name": "matrix" }],
"activation": {
"onStartup": false
"onStartup": false,
"onCommands": ["matrix"]
},
"channels": ["matrix"],
"channelEnvVars": {

View File

@@ -1,7 +1,9 @@
{
"id": "memory-lancedb",
"commandAliases": [{ "name": "ltm" }],
"activation": {
"onStartup": false
"onStartup": false,
"onCommands": ["ltm"]
},
"kind": "memory",
"contracts": {

View File

@@ -138,6 +138,13 @@ export function resolveMissingPluginCommandMessage(
const parentPluginId = commandAlias?.pluginId;
if (parentPluginId) {
if (allow.length > 0 && !allow.includes(parentPluginId)) {
if (parentPluginId === normalizedPluginId) {
return (
`The \`openclaw ${normalizedPluginId}\` command is unavailable because ` +
`\`plugins.allow\` excludes "${normalizedPluginId}". Add "${normalizedPluginId}" to ` +
`\`plugins.allow\` if you want that bundled plugin CLI surface.`
);
}
return (
`"${normalizedPluginId}" is not a plugin; it is a command provided by the ` +
`"${parentPluginId}" plugin. Add "${parentPluginId}" to \`plugins.allow\` ` +

View File

@@ -21,7 +21,7 @@ describe("manifest command aliases", () => {
]);
});
it("resolves aliases without treating plugin ids as command aliases", () => {
it("resolves explicit same-id aliases without treating other plugin ids as aliases", () => {
const registry = {
plugins: [
{
@@ -33,6 +33,10 @@ describe("manifest command aliases", () => {
enabledByDefault: true,
commandAliases: [{ name: "legacy-memory" }],
},
{
id: "matrix",
commandAliases: [{ name: "matrix" }],
},
],
};
@@ -46,6 +50,12 @@ describe("manifest command aliases", () => {
enabledByDefault: true,
name: "legacy-memory",
});
expect(
resolveManifestCommandAliasOwnerInRegistry({ command: "matrix", registry }),
).toMatchObject({
pluginId: "matrix",
name: "matrix",
});
});
it("resolves agent tool owners from contracts.tools", () => {

View File

@@ -115,15 +115,15 @@ export function resolveManifestCommandAliasOwnerInRegistry(params: {
const commandIsPluginId = params.registry.plugins.some(
(plugin) => normalizeOptionalLowercaseString(plugin.id) === normalizedCommand,
);
if (commandIsPluginId) {
return undefined;
}
for (const plugin of params.registry.plugins) {
const alias = plugin.commandAliases?.find(
(entry) => normalizeOptionalLowercaseString(entry.name) === normalizedCommand,
);
if (alias) {
if (commandIsPluginId && normalizeOptionalLowercaseString(plugin.id) !== normalizedCommand) {
continue;
}
return {
...alias,
pluginId: plugin.id,