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
11 changes: 7 additions & 4 deletions hermes_cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -13862,9 +13862,10 @@ def cmd_sessions(args):
print(f"Error: Could not open session database: {e}")
return

# Hide third-party tool sessions by default, but honour explicit --source
# Hide background/internal session sources by default, but honour explicit --source.
# `action` was already initialized at the start of cmd_sessions().
_source = getattr(args, "source", None)
_exclude = None if _source else ["tool"]
_exclude = None if _source else ["tool", "cron"]

if action == "list":
from hermes_state import workspace_key as _ws_key
Expand Down Expand Up @@ -14490,9 +14491,11 @@ def _export_one(session_id: str):
elif action == "browse":
limit = getattr(args, "limit", 500) or 500
source = getattr(args, "source", None)
_browse_exclude = None if source else ["tool"]
_browse_exclude = None if source else ["tool", "cron"]
sessions = db.list_sessions_rich(
source=source, exclude_sources=_browse_exclude, limit=limit
source=source,
exclude_sources=_browse_exclude,
limit=limit,
)
db.close()
if not sessions:
Expand Down
68 changes: 67 additions & 1 deletion tests/hermes_cli/test_session_browse.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from unittest.mock import MagicMock, patch


from hermes_cli.main import _session_browse_picker
from hermes_cli.main import _session_browse_picker, main as hermes_main


# ─── Sample session data ──────────────────────────────────────────────────────
Expand Down Expand Up @@ -442,6 +442,72 @@ def mock_import(name, *args, **kwargs):

assert result == "s1"

def test_browse_hides_cron_and_tool_sessions_by_default(self, monkeypatch):
"""Browse should exclude cron/tool sources unless the user explicitly asks for one."""
mock_db = MagicMock()
mock_db.list_sessions_rich.return_value = []

monkeypatch.setattr("hermes_state.SessionDB", lambda: mock_db)
monkeypatch.setattr("sys.argv", ["hermes", "sessions", "browse"])

hermes_main()

mock_db.list_sessions_rich.assert_called_once_with(
source=None,
exclude_sources=["tool", "cron"],
limit=500,
)
mock_db.close.assert_called_once()

def test_browse_source_filter_disables_default_exclusions(self, monkeypatch):
"""Explicit --source should bypass default source exclusions."""
mock_db = MagicMock()
mock_db.list_sessions_rich.return_value = []

monkeypatch.setattr("hermes_state.SessionDB", lambda: mock_db)
monkeypatch.setattr("sys.argv", ["hermes", "sessions", "browse", "--source", "cron"])

hermes_main()

mock_db.list_sessions_rich.assert_called_once_with(
source="cron",
exclude_sources=None,
limit=500,
)
mock_db.close.assert_called_once()

def test_list_hides_cron_and_tool_sessions_by_default(self, monkeypatch):
"""List should exclude cron/tool sources unless the user explicitly asks for one."""
mock_db = MagicMock()
mock_db.list_sessions_rich.return_value = []

monkeypatch.setattr("hermes_state.SessionDB", lambda: mock_db)
monkeypatch.setattr("sys.argv", ["hermes", "sessions", "list"])

hermes_main()

mock_db.list_sessions_rich.assert_called_once_with(
source=None,
exclude_sources=["tool", "cron"],
limit=20,
)

def test_list_source_filter_disables_default_exclusions(self, monkeypatch):
"""Explicit --source should bypass list default source exclusions too."""
mock_db = MagicMock()
mock_db.list_sessions_rich.return_value = []

monkeypatch.setattr("hermes_state.SessionDB", lambda: mock_db)
monkeypatch.setattr("sys.argv", ["hermes", "sessions", "list", "--source", "cron"])

hermes_main()

mock_db.list_sessions_rich.assert_called_once_with(
source="cron",
exclude_sources=None,
limit=20,
)


# ─── Edge cases ──────────────────────────────────────────────────────────────

Expand Down