mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-29 15:31:38 +08:00
Compare commits
1 Commits
fix/plugin
...
hermes/her
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a456b50a3f |
50
cli.py
50
cli.py
@@ -3052,10 +3052,56 @@ class HermesCLI:
|
|||||||
print(f" Config File: {config_path} {config_status}")
|
print(f" Config File: {config_path} {config_status}")
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
def _list_recent_sessions(self, limit: int = 10) -> list[dict[str, Any]]:
|
||||||
|
"""Return recent CLI sessions for in-chat browsing/resume affordances."""
|
||||||
|
if not self._session_db:
|
||||||
|
return []
|
||||||
|
try:
|
||||||
|
sessions = self._session_db.list_sessions_rich(
|
||||||
|
source="cli",
|
||||||
|
limit=limit,
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
return []
|
||||||
|
return [s for s in sessions if s.get("id") != self.session_id]
|
||||||
|
|
||||||
|
def _show_recent_sessions(self, *, reason: str = "history", limit: int = 10) -> bool:
|
||||||
|
"""Render recent sessions inline from the active chat TUI.
|
||||||
|
|
||||||
|
Returns True when something was shown, False if no session list was available.
|
||||||
|
"""
|
||||||
|
sessions = self._list_recent_sessions(limit=limit)
|
||||||
|
if not sessions:
|
||||||
|
return False
|
||||||
|
|
||||||
|
from hermes_cli.main import _relative_time
|
||||||
|
|
||||||
|
print()
|
||||||
|
print("+" + "-" * 86 + "+")
|
||||||
|
print("|" + "Recent Sessions".center(86) + "|")
|
||||||
|
print("+" + "-" * 86 + "+")
|
||||||
|
print(f" {'Title':<30} {'Preview':<30} {'Last Active':<12} ID")
|
||||||
|
print(f" {'─' * 30} {'─' * 30} {'─' * 12} {'─' * 18}")
|
||||||
|
for session in sessions:
|
||||||
|
title = (session.get("title") or "—")[:30]
|
||||||
|
preview = (session.get("preview") or "")[:30]
|
||||||
|
last_active = _relative_time(session.get("last_active"))
|
||||||
|
print(f" {title:<30} {preview:<30} {last_active:<12} {session['id']}")
|
||||||
|
|
||||||
|
print()
|
||||||
|
if reason == "history":
|
||||||
|
print("(._.) No messages in the current chat yet.")
|
||||||
|
print(" Above are recent sessions you can resume with /resume <session id or title>.")
|
||||||
|
else:
|
||||||
|
print(" Use /resume <session id or title> to switch to one of these sessions.")
|
||||||
|
print()
|
||||||
|
return True
|
||||||
|
|
||||||
def show_history(self):
|
def show_history(self):
|
||||||
"""Display conversation history."""
|
"""Display conversation history."""
|
||||||
if not self.conversation_history:
|
if not self.conversation_history:
|
||||||
print("(._.) No conversation history yet.")
|
if not self._show_recent_sessions(reason="history"):
|
||||||
|
print("(._.) No conversation history yet.")
|
||||||
return
|
return
|
||||||
|
|
||||||
preview_limit = 400
|
preview_limit = 400
|
||||||
@@ -3180,6 +3226,8 @@ class HermesCLI:
|
|||||||
|
|
||||||
if not target:
|
if not target:
|
||||||
_cprint(" Usage: /resume <session_id_or_title>")
|
_cprint(" Usage: /resume <session_id_or_title>")
|
||||||
|
if self._show_recent_sessions(reason="resume"):
|
||||||
|
return
|
||||||
_cprint(" Tip: Use /history or `hermes sessions list` to find sessions.")
|
_cprint(" Tip: Use /history or `hermes sessions list` to find sessions.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -191,6 +191,60 @@ class TestHistoryDisplay:
|
|||||||
assert "A" * 250 in output
|
assert "A" * 250 in output
|
||||||
assert "A" * 250 + "..." not in output
|
assert "A" * 250 + "..." not in output
|
||||||
|
|
||||||
|
def test_history_shows_recent_sessions_when_current_chat_is_empty(self, capsys):
|
||||||
|
cli = _make_cli()
|
||||||
|
cli.session_id = "current"
|
||||||
|
cli._session_db = MagicMock()
|
||||||
|
cli._session_db.list_sessions_rich.return_value = [
|
||||||
|
{
|
||||||
|
"id": "current",
|
||||||
|
"title": "Current",
|
||||||
|
"preview": "Current preview",
|
||||||
|
"last_active": 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "20260401_201329_d85961",
|
||||||
|
"title": "Checking Running Hermes Agent",
|
||||||
|
"preview": "check running gateways for hermes agent",
|
||||||
|
"last_active": 0,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
cli.show_history()
|
||||||
|
output = capsys.readouterr().out
|
||||||
|
|
||||||
|
assert "Recent Sessions" in output
|
||||||
|
assert "Checking Running Hermes Agent" in output
|
||||||
|
assert "20260401_201329_d85961" in output
|
||||||
|
assert "No messages in the current chat yet." in output
|
||||||
|
assert "Current preview" not in output
|
||||||
|
|
||||||
|
def test_resume_without_target_lists_recent_sessions(self, capsys):
|
||||||
|
cli = _make_cli()
|
||||||
|
cli.session_id = "current"
|
||||||
|
cli._session_db = MagicMock()
|
||||||
|
cli._session_db.list_sessions_rich.return_value = [
|
||||||
|
{
|
||||||
|
"id": "current",
|
||||||
|
"title": "Current",
|
||||||
|
"preview": "Current preview",
|
||||||
|
"last_active": 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "20260401_201329_d85961",
|
||||||
|
"title": "Checking Running Hermes Agent",
|
||||||
|
"preview": "check running gateways for hermes agent",
|
||||||
|
"last_active": 0,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
cli._handle_resume_command("/resume")
|
||||||
|
output = capsys.readouterr().out
|
||||||
|
|
||||||
|
assert "Recent Sessions" in output
|
||||||
|
assert "Checking Running Hermes Agent" in output
|
||||||
|
assert "Use /resume <session id or title> to switch" in output
|
||||||
|
|
||||||
|
|
||||||
class TestRootLevelProviderOverride:
|
class TestRootLevelProviderOverride:
|
||||||
"""Root-level provider/base_url in config.yaml must NOT override model.provider."""
|
"""Root-level provider/base_url in config.yaml must NOT override model.provider."""
|
||||||
|
|||||||
Reference in New Issue
Block a user