fix(config): give actionable guidance when command names are used in plugins.allow (#64191)#64242
Conversation
Greptile SummaryThis PR fixes a usability trap where putting Confidence Score: 5/5Safe to merge — focused bug fix with good test coverage and no behavioral changes to existing enforcement. All findings are P2 style/maintenance concerns. The active-memory self-mapping is dead code, and the hardcoded src/cli/run-main.ts (hardcoded CLI alternative message), src/config/validation.ts (dead active-memory self-mapping entry) Prompt To Fix All With AIThis is a comment left during a code review.
Path: src/cli/run-main.ts
Line: 88-91
Comment:
**Hardcoded CLI alternative couples message to a single entry**
The third sentence hardcodes `` `openclaw memory` `` regardless of which entry matched in `RUNTIME_COMMAND_TO_PLUGIN_ID`. If a future entry is added to the map (e.g. `voice → talk-voice`), the guidance would incorrectly tell the user to run `openclaw memory` for CLI voice operations. Consider storing the CLI command alongside the plugin id in the map value:
```suggestion
// Check if this is a runtime slash command rather than a CLI command.
const runtimeEntry = RUNTIME_COMMAND_TO_PLUGIN_ID[normalizedPluginId];
if (runtimeEntry) {
const { parentPluginId, cliAlternative } = runtimeEntry;
return (
`"${normalizedPluginId}" is a runtime slash command (/${normalizedPluginId}), not a CLI command. ` +
`It is provided by the "${parentPluginId}" plugin. ` +
(cliAlternative
? `Use \`${cliAlternative}\` for CLI operations, or \`/${normalizedPluginId}\` in a chat session.`
: `Use \`/${normalizedPluginId}\` in a chat session.`)
);
}
```
(Requires updating the map type and the single `dreaming` entry to `{ parentPluginId: "memory-core", cliAlternative: "openclaw memory" }`.)
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: src/config/validation.ts
Line: 50
Comment:
**Self-mapping entry is unreachable**
`"active-memory": "active-memory"` will never produce the redirect warning because the downstream guard requires `parentPluginId !== pluginId`. When both values are `"active-memory"` the condition is false, and execution falls through to the generic `pushMissingPluginIssue` path — identical to if the entry weren't in the map at all. Either remove the entry or replace it with a comment explaining the intent.
```suggestion
// dreaming is a slash command registered by memory-core; its CLI surface is `openclaw memory`.
dreaming: "memory-core",
// voice, phone, pair are CLI command names whose parent plugin ids differ.
voice: "talk-voice",
phone: "phone-control",
pair: "device-pair",
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "fix(config): give actionable guidance wh..." | Re-trigger Greptile |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3aef0972f5
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
604c6ed to
680b96d
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 680b96db17
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…plugins.allow (openclaw#64191) When users put a runtime command name like "dreaming" into `plugins.allow`, validation now explains that it is a command provided by a specific plugin (e.g. "memory-core") and suggests using the plugin id instead, rather than the generic "plugin not found" warning that previously created a circular trap with the CLI error message. Similarly, running `openclaw dreaming` from the CLI now explains that `/dreaming` is a runtime slash command (not a CLI command) and points users to `openclaw memory` for CLI operations or `/dreaming` in a chat session. Fixes two related UX problems: 1. `plugins.allow: ["dreaming"]` → validation warned "plugin not found" 2. `openclaw dreaming status` → CLI said "add dreaming to plugins.allow" (which then triggered problem 1) Root cause: "dreaming" is a slash command registered by the memory-core plugin via `api.registerCommand()`, not a standalone plugin or CLI command.
204e88e to
4e01de8
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4e01de8cbb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (commandAlias.kind === "runtime-slash") { | ||
| const cliHint = commandAlias.cliCommand | ||
| ? `Use \`openclaw ${commandAlias.cliCommand}\` for related CLI operations, or ` | ||
| : "Use "; | ||
| return ( |
There was a problem hiding this comment.
Respect deny/global disable before slash-command guidance
This branch returns the runtime slash command hint as soon as commandAliases.kind === "runtime-slash", but it only checks plugins.allow and plugins.entries.<id>.enabled first. If the owning plugin is disabled through plugins.enabled=false or blocked by plugins.deny, openclaw dreaming will still tell users to use /dreaming, even though that command surface is unavailable in runtime. This creates a misleading diagnostic path for valid config states and should be gated on full plugin activation (including deny/global disable), not just allowlist and entry-level disablement.
Useful? React with 👍 / 👎.
|
Landed via rebase onto main.
Thanks @feiskyer! |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7dde05b50b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const resolved = runtime.resolvePluginSetupCliBackend(params); | ||
| if (resolved) { | ||
| return resolved; | ||
| } | ||
| } |
There was a problem hiding this comment.
Avoid manifest fallback after runtime backend resolution fails
This now falls back to resolveBundledSetupCliBackends() whenever runtime.resolvePluginSetupCliBackend() returns undefined, not just when the runtime module is unavailable. In failure cases (for example setup import/registration drift), that fallback trusts manifest cliBackends metadata and can report a backend as available even though setup resolution failed, which can misclassify providers via isCliProvider() and send model selection down the wrong path. The manifest fallback should only run when setup-runtime loading is unavailable, not when runtime lookup explicitly misses.
Useful? React with 👍 / 👎.
| if (commandAlias.kind === "runtime-slash") { | ||
| const cliHint = commandAlias.cliCommand | ||
| ? `Use \`openclaw ${commandAlias.cliCommand}\` for related CLI operations, or ` | ||
| : "Use "; | ||
| return ( |
There was a problem hiding this comment.
Return alias guidance even when alias kind is omitted
Alias-specific handling only returns early for kind === "runtime-slash", but manifest parsing accepts commandAliases entries without a kind. For those valid aliases, this branch falls through to the generic allowlist check and can tell users to add the alias itself to plugins.allow even when the parent plugin is already allowlisted, which is incorrect because aliases are not plugin IDs. This recreates misleading guidance for kindless aliases.
Useful? React with 👍 / 👎.
Summary
"dreaming"inplugins.allowcauses a "plugin not found" warning, and runningopenclaw dreamingfrom CLI misleadingly tells users to add"dreaming"toplugins.allow— creating a circular trap where neither path works./dreamingis a runtime slash command frommemory-core, not a standalone plugin or CLI command. The error messages actively mislead them.memory-core) and the correct usage (/dreamingin chat oropenclaw memoryon CLI).plugins.allowenforcement works. Generic "plugin not found" handling for truly unknown ids is untouched.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
Root Cause (if applicable)
dreamingis a runtime slash command registered by thememory-coreplugin viaapi.registerCommand(), but both config validation and CLI command resolution treat unrecognized names as plugin ids. Neither path knows that some command names map to parent plugins.memory-coreplugin registers CLI commands undermemory(viaapi.registerCli()) but its slash command underdreaming(viaapi.registerCommand()). The naming mismatch between the CLI surface (memory) and the slash command (dreaming) makes this confusing.Regression Test Plan (if applicable)
src/cli/run-main.test.ts— 2 new tests forresolveMissingPluginCommandMessage("dreaming")src/config/config.plugin-validation.test.ts— 1 new test forplugins.allow: ["dreaming"]"dreaming"inplugins.allowproduces a redirect warning (not generic "plugin not found")openclaw dreamingproduces a runtime-command explanation (not a misleadingplugins.allowsuggestion)plugins.allowis setSecurity Impact
Human Verification (required)
Verified scenarios:
plugins.allow: ["dreaming"]+openclaw doctor→ shows redirect warning tomemory-core✅openclaw dreaming statuswithplugins.allow: ["memory-core"]→ shows runtime slash command explanation ✅openclaw dreaming statuswithoutplugins.allow→ same explanation ✅openclaw memory --help→ still works normally ✅pnpm checkpasses (types, lint, all checks) ✅Edge cases checked:
COMMAND_NAME_TO_PLUGIN_IDentries where command name equals plugin id (e.g.active-memory) are skipped by theparentPluginId !== pluginIdguardWhat I did NOT verify:
/dreamingslash command (not changed by this PR)Review Conversations
Compatibility / Migration
Risks and Mitigations
COMMAND_NAME_TO_PLUGIN_IDmap could become stale if plugins rename their commands.