Skip to content
Merged
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
22 changes: 22 additions & 0 deletions hermes_cli/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,28 @@ def llm(self) -> Any:
self._llm = PluginLlm(plugin_id=plugin_id)
return self._llm

# -- profile awareness --------------------------------------------------

@property
def profile_name(self) -> str:
"""Return the active Hermes profile name (e.g. ``"default"``).

Derived from ``HERMES_HOME`` via
:func:`hermes_cli.profiles.get_active_profile_name`, so it works in
every execution context — interactive CLI, gateway, and
kanban-spawned worker sessions alike — without depending on
``_cli_ref`` (which is ``None`` outside an interactive CLI run).

Returns ``"default"`` for the default profile, the profile id when
running under ``~/.hermes/profiles/<name>``, or ``"custom"`` when
``HERMES_HOME`` points somewhere unrecognized.
"""
try:
from hermes_cli.profiles import get_active_profile_name
return get_active_profile_name()
except Exception:
return "default"

# -- tool registration --------------------------------------------------

def register_tool(
Expand Down
35 changes: 35 additions & 0 deletions tests/hermes_cli/test_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -1867,3 +1867,38 @@ def test_debug_handler_idempotent(self, monkeypatch):
plugins_mod._PLUGINS_DEBUG = original_debug
plugins_mod.logger.setLevel(original_level)
plugins_mod.logger.handlers = original_handlers


class TestPluginContextProfileName:
"""ctx.profile_name resolves from HERMES_HOME in every context."""

def _ctx(self):
mgr = PluginManager()
manifest = PluginManifest(name="test-plugin", source="user")
return PluginContext(manifest, mgr)

def test_default_profile(self, tmp_path, monkeypatch):
"""HERMES_HOME at the root resolves to 'default'."""
home = tmp_path / ".hermes"
home.mkdir()
monkeypatch.setattr(Path, "home", lambda: tmp_path)
monkeypatch.setenv("HERMES_HOME", str(home))
assert self._ctx().profile_name == "default"

def test_named_profile(self, tmp_path, monkeypatch):
"""HERMES_HOME under profiles/<name> resolves to that name."""
prof = tmp_path / ".hermes" / "profiles" / "coder"
prof.mkdir(parents=True)
monkeypatch.setattr(Path, "home", lambda: tmp_path)
monkeypatch.setenv("HERMES_HOME", str(prof))
assert self._ctx().profile_name == "coder"

def test_works_without_cli_ref(self, tmp_path, monkeypatch):
"""profile_name does not depend on _cli_ref (None in worker sessions)."""
prof = tmp_path / ".hermes" / "profiles" / "worker1"
prof.mkdir(parents=True)
monkeypatch.setattr(Path, "home", lambda: tmp_path)
monkeypatch.setenv("HERMES_HOME", str(prof))
ctx = self._ctx()
assert ctx._manager._cli_ref is None
assert ctx.profile_name == "worker1"
Loading