Skip to content

fix(plugins): refuse enable/disable on passive plugin kinds with a pointer to the real switch - #59183

Open
sam7894604 wants to merge 2 commits into
NousResearch:mainfrom
sam7894604:fix/plugins-passive-kind-guard
Open

fix(plugins): refuse enable/disable on passive plugin kinds with a pointer to the real switch#59183
sam7894604 wants to merge 2 commits into
NousResearch:mainfrom
sam7894604:fix/plugins-passive-kind-guard

Conversation

@sam7894604

Copy link
Copy Markdown
Contributor

What

hermes plugins enable/disable <name> silently did nothing for passive plugin kinds — kinds whose activation is controlled elsewhere, not by the enable/disable switch. The command returned success but nothing changed, leaving the user unsure why.

Why

Passive plugin kinds (e.g. memory providers and other config-driven kinds) are switched on/off through their own config, not through plugins enable/disable. Invoking enable/disable on them was a no-op with no feedback. This makes the command recognize passive kinds and refuse with a clear message pointing to the real switch, instead of a silent no-op that looks like it worked.

Changes

  • hermes_cli/plugins_cmd.py — detect passive plugin kinds and refuse enable/disable with a pointer to the actual control.
  • tests/hermes_cli/test_plugins_enable_passive_kinds.py — new coverage.

Testing

pytest tests/hermes_cli/test_plugins_enable_passive_kinds.py -q -> 5 passed.

Cleanly cherry-picked onto current main; touches only the two files above (no unrelated changes).

…o the real switch

`hermes plugins enable gemini` printed a green success message and wrote
model-providers/gemini into plugins.enabled — but nothing ever reads that
flag for model providers: the general loader explicitly skips
kind: model-provider (handled by providers/__init__.py's own discovery,
selected via `hermes model` / model.provider) and kind: exclusive
(activated via `<category>.provider`). Same for disable: the entry lands
in plugins.disabled, the loader records it for introspection, and the
provider registers anyway.

The success message misleads users into believing they switched a
provider on or off. Found in the wild: a config with
model-providers/gemini in BOTH plugins.enabled (as a stray string) and
plugins.disabled, while the gemini provider had been registered and
usable the whole time.

enable/disable now detect the manifest kind and print what actually
controls the plugin, changing nothing:

  ! model-providers/gemini is a model provider — it is not controlled by
    plugins.enabled/disabled (providers register automatically at startup).
      To use it:       run `hermes model` and pick it, or set model.provider.
      To stop using it: select a different provider; remove its API key.
    Nothing was changed.
@alt-glitch alt-glitch added type/bug Something isn't working comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have labels Jul 5, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing the misleading success path; the model-provider premise is verified on current main: cmd_enable writes the general allow-list (hermes_cli/plugins_cmd.py:829-862), while provider discovery imports model-provider directories without reading that list (providers/__init__.py:156-171).

Problems

  • The new _plugin_kind() only recognizes an explicit manifest kind (hermes_cli/plugins_cmd.py:835 in this PR). Current bundled memory providers are excluded from _discover_all_plugins() (hermes_cli/plugins_cmd.py:1027-1034) and their manifests, including plugins/memory/honcho/plugin.yaml:1-7, do not declare kind: exclusive.
  • User memory providers can be classified as exclusive by the existing __init__.py heuristic (hermes_cli/plugins.py:1600-1627), which this new parser also bypasses. The synthetic explicit-kind test does not cover either production path.

Suggested changes

  • Route memory-provider detection through plugins.memory discovery (and preserve the existing model-provider route), then add tests for the bundled and inferred-memory conventions.

Automated hermes-sweeper review.

Comment thread hermes_cli/plugins_cmd.py Outdated
try:
import yaml

data = yaml.safe_load(mf.read_text(encoding="utf-8")) or {}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This explicit manifest lookup does not match the effective kind rules. Bundled memory providers are excluded from _discover_all_plugins() and their manifests (for example plugins/memory/honcho/plugin.yaml) omit kind; user memory providers can instead be inferred as exclusive from __init__.py. Route memory detection through the category discovery path or share the existing effective-kind logic.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 15, 2026
Address review: _plugin_kind() no longer re-reads the raw manifest `kind` and no longer misses bundled memory providers.

- Reuse PluginManager._parse_manifest so the register_memory_provider / register_provider heuristic (for manifests without an explicit kind) is shared, instead of defaulting user providers to standalone.

- Recognize memory providers through plugins.memory discover_memory_providers(): bundled providers (e.g. honcho) ship without kind: exclusive and are excluded from _discover_all_plugins(), so cmd_enable/cmd_disable now intercept them before the general resolver and show the passive-kind hint instead of a misleading 'not installed' error.

- Add production-path tests: bundled memory provider via category discovery, and the heuristic user memory/model provider paths (the prior tests only covered synthetic explicit-kind manifests).
@sam7894604

Copy link
Copy Markdown
Contributor Author

Thanks for the review — both points are addressed in the latest push.

  • Share the loader's kind classification. _plugin_kind() no longer re-reads the raw manifest kind; it now delegates to PluginManager._parse_manifest, so the register_memory_provider / register_provider heuristic used for manifests that omit an explicit kind is applied consistently. A user-installed memory/model provider without kind: is now classified exclusive / model-provider instead of defaulting to standalone.
  • Recognize bundled memory providers via plugins.memory discovery. Bundled providers (e.g. plugins/memory/honcho/plugin.yaml) ship without kind: exclusive and are excluded from _discover_all_plugins(), so they never reached the kind check. _plugin_kind() now consults discover_memory_providers(), and cmd_enable / cmd_disable intercept memory providers before the general resolver — so hermes plugins enable honcho prints the passive-kind hint (pointing at memory.provider) instead of a misleading "not installed" error. The model-provider path is unchanged.
  • Tests — production paths, not just synthetic manifests. Added coverage for (1) a bundled memory provider recognized through category discovery while absent from _discover_all_plugins(), and (2) the heuristic user memory- and model-provider paths. The existing suite plus the new cases pass (8/8; broader plugins_cmd suite green aside from unrelated _curses/symlink cases that don't run on this platform).

No rebase needed — this is a single follow-up commit on top of the existing branch and it stays mergeable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants