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
52 changes: 51 additions & 1 deletion cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -9168,6 +9168,50 @@ def _show_session_status(self):
model = getattr(self, "model", None) or "(unknown)"
is_running = bool(getattr(self, "_agent_running", False))

# Reasoning level (C-02): resolve the effective effort for display.
reasoning_label = None
try:
rc = getattr(agent, "reasoning_config", None) or getattr(self, "reasoning_config", None)
if isinstance(rc, dict):
if rc.get("enabled") is False:
reasoning_label = "off"
elif rc.get("effort"):
reasoning_label = str(rc.get("effort"))
show_r = getattr(self, "show_reasoning", None)
if reasoning_label:
reasoning_label += f" (display: {'on' if show_r else 'off'})" if show_r is not None else ""
except Exception:
reasoning_label = None

# Approval mode (C-02).
approval_label = None
try:
from tools.approval import _get_approval_mode, is_approval_bypass_active_for_session
approval_label = _get_approval_mode()
try:
if is_approval_bypass_active_for_session(getattr(self, "session_key", "") or ""):
approval_label += " (YOLO bypass active)"
except Exception:
pass
except Exception:
approval_label = None

# Context window usage (C-02): reuse the status-bar snapshot which
# already computes tokens / max / percent.
ctx_label = None
try:
snap = self._get_status_bar_snapshot()
ctx_tokens = snap.get("context_tokens") or 0
ctx_max = snap.get("context_length")
ctx_pct = snap.get("context_percent")
if ctx_max:
left = ""
if isinstance(ctx_pct, (int, float)):
left = f"{max(0, 100 - int(ctx_pct))}% left · "
ctx_label = f"{left}{ctx_tokens:,} / {ctx_max:,} tokens used"
except Exception:
ctx_label = None

lines = [
"Hermes CLI Status",
"",
Expand All @@ -9176,8 +9220,14 @@ def _show_session_status(self):
]
if title:
lines.append(f"Title: {title}")
lines.append(f"Model: {model} ({provider})")
if reasoning_label:
lines.append(f"Reasoning: {reasoning_label}")
if approval_label:
lines.append(f"Approvals: {approval_label}")
if ctx_label:
lines.append(f"Context: {ctx_label}")
lines.extend([
f"Model: {model} ({provider})",
f"Created: {created_at.strftime('%Y-%m-%d %H:%M')}",
f"Last Activity: {updated_at.strftime('%Y-%m-%d %H:%M')}",
f"Tokens: {total_tokens:,}",
Expand Down
24 changes: 24 additions & 0 deletions tests/cli/test_cli_status_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,30 @@ def test_show_session_status_prints_gateway_style_summary():
assert kwargs.get("markup") is False


def test_show_session_status_includes_reasoning_approvals_context():
"""C-02: /status surfaces reasoning level, approval mode, and context %."""
cli_obj = _make_cli()
cli_obj.agent = SimpleNamespace(session_total_tokens=1000, session_api_calls=2,
reasoning_config={"enabled": True, "effort": "high"})
cli_obj.reasoning_config = {"enabled": True, "effort": "high"}
cli_obj.show_reasoning = True
cli_obj.session_key = ""
cli_obj._session_db.get_session.return_value = {"started_at": 1775791440}
cli_obj._get_status_bar_snapshot = lambda: {
"context_tokens": 50000, "context_length": 200000, "context_percent": 25,
}

with patch("cli.display_hermes_home", return_value="~/.hermes"), \
patch("tools.approval._get_approval_mode", return_value="manual"), \
patch("tools.approval.is_approval_bypass_active_for_session", return_value=False):
cli_obj._show_session_status()

printed = "\n".join(str(call.args[0]) for call in cli_obj.console.print.call_args_list)
assert "Reasoning: high (display: on)" in printed
assert "Approvals: manual" in printed
assert "Context: 75% left · 50,000 / 200,000 tokens used" in printed


def test_profile_command_reports_custom_root_profile(monkeypatch, tmp_path, capsys):
"""Profile detection works for custom-root deployments (not under ~/.hermes)."""
cli_obj = _make_cli()
Expand Down
Loading