fix(cli): clarify plugin tool command mistakes#79693
Conversation
|
Codex review: needs real behavior proof before merge. Summary Reproducibility: yes. source-level. Current main can emit the misleading plugins.allow fallback for a root token that is not a CLI command or command alias, and the PR's remaining denylist mismatch is visible by comparing the new resolver with current runtime tool discovery. Real behavior proof Next step before merge Security Review findings
Review detailsBest possible solution: Keep the manifest-backed agent-tool diagnostic, but make tool-owner resolution share the runtime plugin policy, including plugins.deny, before merging. Do we have a high-confidence way to reproduce the issue? Yes, source-level. Current main can emit the misleading plugins.allow fallback for a root token that is not a CLI command or command alias, and the PR's remaining denylist mismatch is visible by comparing the new resolver with current runtime tool discovery. Is this the best way to solve the issue? No. The diagnostic direction is the narrow maintainable fix, but this patch must honor plugins.deny for the owning plugin and include focused regression coverage before it is the best solution. Full review comments:
Overall correctness: patch is incorrect Acceptance criteria:
What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 2e29090c3713. Re-review progress:
|
…tool name When `openclaw <name>` does not match a CLI subcommand or a plugin id, the unknown-subcommand handler now first looks up <name> against the manifest plugin tool registry. If <name> is an agent tool declared by a plugin (e.g. `lcm_recent` from `lossless-claw`), emit a clear 'this is an agent tool, not a CLI subcommand' error pointing at model tool-use instead of the misleading `plugins.allow` suggestion. The previous error told the user to add the tool name to `plugins.allow`, but `plugins.allow` accepts plugin ids (not tool names), and config patches against it are rejected by the protected-config-paths guard. In the wild this sent an agent down 3 restart cycles trying to 'fix' config that was never the problem. Filtering: the runtime resolver consults the full manifest snapshot and filters through `isManifestPluginAvailableForControlPlane` (covering `plugins.allow`/`plugins.deny`/`plugins.entries[id].enabled`/installed index) plus per-tool `hasManifestToolAvailability` (covering `toolMetadata.configSignals` like Feishu's `appId`/`appSecret` gate). The diagnostic also re-checks `plugins.allow` and `plugins.entries[X].enabled` for the OWNING plugin before emitting, so denied/disabled plugins are not falsely attributed. Wording: when ownership is only manifest-provable (per-account `enabled` flags and per-tool toggles in the Feishu family are runtime-only and not declarable as configSignals, so the manifest is necessarily an over-approximation), emit a softer 'may be provided by the X plugin' message instead of asserting 'registered by'. The strong wording is reserved for the case where both control-plane availability and tool availability pass. Fall-throughs: if <name> is not a registered tool, the existing `plugins.allow` and `plugins.entries.<id>.enabled` suggestions are emitted unchanged. The new branch only fires when the tool-registry lookup matches AND the owning plugin passes availability filters. Closes #77214.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2fd02077a2
ℹ️ 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 ownerEnabled = | ||
| config?.plugins?.entries?.[toolOwner.pluginId]?.enabled !== false && | ||
| (allow.length === 0 || allow.includes(toolOwner.pluginId)); |
There was a problem hiding this comment.
Respect plugins.deny before attributing agent tool ownership
This new tool-diagnostic path only gates ownership on plugins.allow and plugins.entries[...].enabled, so a tool from a plugin listed in plugins.deny can still be reported as "available from" that plugin. In that configuration, openclaw <tool_name> will produce an inaccurate hint because denylisted plugins are not loadable; please include a denylist check here (or reuse the same activation-state predicate used for plugin enablement) before emitting the positive agent-tool message.
Useful? React with 👍 / 👎.
2fd0207 to
aee87c6
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aee87c6346
ℹ️ 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 pluginAvailable = isManifestPluginAvailableForControlPlane({ | ||
| snapshot, | ||
| plugin, | ||
| config: params.config, | ||
| }); |
There was a problem hiding this comment.
Honor plugins.deny when resolving tool owners
This resolver assumes isManifestPluginAvailableForControlPlane enforces plugins.deny, but for bundled plugins that helper returns true unconditionally, so a denylisted bundled plugin can still be reported as owning a tool and drive the CLI message that the tool is "available from" that plugin. Fresh evidence in this commit is the new resolveManifestToolOwner flow using this check before returning ownership, which means openclaw <tool_name> can produce a false positive attribution whenever plugins.deny blocks the owning bundled plugin.
Useful? React with 👍 / 👎.
Summary
openclaw lcm_recentreaches the plugin-tool diagnostic instead of the generic unknown-command path.Real behavior proof
openclaw <toolName>used to report generic CLI/proxy guidance or the misleadingplugins.allowsuggestion when<toolName>was an agent tool, not a CLI command.OPENCLAW_HOME, temp config, and temp externallossless-clawplugin manifest declaringcontracts.tools=["lcm_recent"].pnpm openclaw lcm_recent.plugins.allowsuggestion.Verification
pnpm test src/cli/run-main.test.ts src/cli/run-main.exit.test.ts src/plugins/manifest-command-aliases.test.tspnpm exec oxfmt --check --threads=1 CHANGELOG.md src/cli/run-main-policy.ts src/cli/run-main.ts src/cli/run-main.test.ts src/cli/run-main.exit.test.ts src/plugins/manifest-command-aliases.ts src/plugins/manifest-command-aliases.runtime.ts src/plugins/manifest-command-aliases.test.tspnpm buildCloses #77214. Supersedes #77221.