Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion hermes_cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -12805,7 +12805,7 @@ def _dispatch_secrets(args): # noqa: ANN001
plugin_parser.set_defaults(func=cmd_info["handler_fn"])
seen_plugin_commands.add(cmd_info["name"])

discover_plugins()
discover_plugins(cli_command=_first_positional_argv())
for cmd_info in get_plugin_manager()._cli_commands.values():
if cmd_info["name"] in seen_plugin_commands:
continue
Expand Down
32 changes: 29 additions & 3 deletions hermes_cli/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -1227,14 +1227,20 @@ def __init__(self) -> None:
# Public
# -----------------------------------------------------------------------

def discover_and_load(self, force: bool = False) -> None:
def discover_and_load(
self,
force: bool = False,
*,
cli_command: Optional[str] = None,
) -> None:
"""Scan all plugin sources and load each plugin found.

When ``force`` is true, clear cached discovery state first so config
changes or newly-added bundled backends become visible in long-lived
sessions without requiring a full agent restart.
"""
if self._discovered and not force:
self._load_deferred_platform_for_cli_command(cli_command)
return
# Safe mode (--safe-mode / HERMES_SAFE_MODE=1): troubleshooting run
# with all customizations disabled. Skip plugin discovery entirely so
Expand Down Expand Up @@ -1268,6 +1274,7 @@ def discover_and_load(self, force: bool = False) -> None:
except BaseException:
self._discovered = False
raise
self._load_deferred_platform_for_cli_command(cli_command)

def _discover_and_load_inner(self) -> None:
"""The actual discovery sweep β€” see :meth:`discover_and_load`."""
Expand Down Expand Up @@ -1700,6 +1707,21 @@ def _loader(_manifest: PluginManifest = manifest) -> None:
)
self._load_plugin(manifest)

def _load_deferred_platform_for_cli_command(
self,
cli_command: Optional[str],
) -> None:
if not cli_command or cli_command in self._cli_commands:
return
for loaded in list(self._plugins.values()):
if not loaded.deferred:
continue
manifest = loaded.manifest
if self._platform_name_from_manifest(manifest) != cli_command:
continue
self._load_plugin(manifest)
return

def _load_plugin(self, manifest: PluginManifest) -> None:
"""Import a plugin module and call its ``register(ctx)`` function."""
loaded = LoadedPlugin(manifest=manifest)
Expand Down Expand Up @@ -1992,13 +2014,17 @@ def get_plugin_manager() -> PluginManager:
return _plugin_manager


def discover_plugins(force: bool = False) -> None:
def discover_plugins(
force: bool = False,
*,
cli_command: Optional[str] = None,
) -> None:
"""Discover and load all plugins.

Default behavior is idempotent. Pass ``force=True`` to rescan plugin
manifests and reload state in the current process.
"""
get_plugin_manager().discover_and_load(force=force)
get_plugin_manager().discover_and_load(force=force, cli_command=cli_command)


def invoke_hook(hook_name: str, **kwargs: Any) -> List[Any]:
Expand Down
Loading
Loading