Skip to content
Closed
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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
B0on
7 changes: 5 additions & 2 deletions hermes_cli/cli_info_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -772,9 +772,12 @@ def _show_insights(self, command: str = "/insights"):
i += 1

try:
from hermes_state import SessionDB
from hermes_state import SessionDB, _default_db_path
from agent.insights import InsightsEngine
db = SessionDB()
if not _default_db_path().exists():
print(" No session data yet.")
return
db = SessionDB(read_only=True)
try:
engine = InsightsEngine(db)
print(engine.format_terminal(engine.generate(days=days, source=source)))
Expand Down
7 changes: 5 additions & 2 deletions hermes_cli/main_agent_cmds.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,12 @@ def cmd_tools(args):
def cmd_insights(args):
db = None
try:
from hermes_state import SessionDB
from hermes_state import SessionDB, _default_db_path
from agent.insights import InsightsEngine
db = SessionDB()
if not _default_db_path().exists():
print("No session data yet.")
return
db = SessionDB(read_only=True)
engine = InsightsEngine(db)
report = engine.generate(days=args.days, source=args.source)
print(engine.format_terminal(report))
Expand Down
34 changes: 34 additions & 0 deletions tests/cli/test_cli_insights_command.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
from unittest.mock import MagicMock, patch
from types import SimpleNamespace

import pytest

from cli import HermesCLI
from hermes_cli.main_agent_cmds import cmd_insights
from hermes_state import _default_db_path


@pytest.fixture(autouse=True)
def _state_db_exists():
# insights short-circuits before opening when state.db is absent.
_default_db_path().parent.mkdir(parents=True, exist_ok=True)
_default_db_path().touch()


class _InsightsEngineStub:
Expand Down Expand Up @@ -45,6 +55,30 @@ def test_cli_insights_keeps_days_flag_and_source(capsys):
assert "days=14 source=discord" in capsys.readouterr().out


def test_insights_opens_state_db_read_only():
# `hermes insights` / `/insights` are readers; a read-write SessionDB
# would take a writer connection on the live gateway's state.db.
runs = (
lambda: HermesCLI.__new__(HermesCLI)._show_insights("/insights 7"),
lambda: cmd_insights(SimpleNamespace(days=30, source=None)),
)
# Fresh install: no state.db yet → no open at all (read-only open needs an existing file).
_default_db_path().unlink()
for run in runs:
with patch("hermes_state.SessionDB") as ctor:
run()
ctor.assert_not_called()
_default_db_path().touch()
for run in runs:
db = MagicMock()
_InsightsEngineStub.calls = []
with patch("hermes_state.SessionDB", return_value=db) as ctor, \
patch("agent.insights.InsightsEngine", _InsightsEngineStub):
run()
ctor.assert_called_once_with(read_only=True)
db.close.assert_called_once()


def test_subcommand_insights_closes_database_when_generation_fails(capsys):
db = MagicMock()
with patch("hermes_state.SessionDB", return_value=db), \
Expand Down
Loading