Skip to content

feat(cli): add /stats slash command for session analytics - #154

Closed
ygd58 wants to merge 29 commits into
NousResearch:mainfrom
ygd58:main
Closed

feat(cli): add /stats slash command for session analytics#154
ygd58 wants to merge 29 commits into
NousResearch:mainfrom
ygd58:main

Conversation

@ygd58

@ygd58 ygd58 commented Feb 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a new /stats slash command to the Hermes CLI that displays session analytics from the existing SQLite state database.

Motivation

The session data is already being collected in ~/.hermes/state.db via hermes_state.py, but there was no way for users to view it from within the CLI. This PR surfaces that data through a new /stats command.

Changes

  • hermes_cli/stats.py (new file): reads from the SQLite session store and renders a stats dashboard with ANSI colors
  • hermes_cli/commands.py: registers /stats in the COMMANDS dict and imports print_stats
  • cli.py: adds /stats entry to the local COMMANDS dict and handles the command in process_command

What it shows

  • Total sessions, turns, and tool calls
  • Token usage (input/output)
  • Platform breakdown
  • Top 5 models used
  • Top 10 tools used
  • Day-of-week activity chart

Notes

  • Zero new dependencies (uses existing hermes_state.SessionDB and hermes_cli.banner helpers)
  • Graceful degradation: handles missing DB, empty DB, and SQLite errors
  • No schema changes required

ygd58 added 29 commits February 26, 2026 11:13
This script provides functions to search Notion pages by title and retrieve database schema properties.
Adds a function to fetch model metadata from Hugging Face.
Added operational guidelines for Hugging Face model expertise.
This function executes a Python code snippet in a secure subprocess, capturing output or errors. It includes error handling for timeouts and system errors.
Added operational guidelines for the Autonomous Code Verification Skill.
This skill enables Hermes to autonomously extend its own capabilities by writing new Python tools from scratch, testing them, and registering them without human intervention.
This script fetches current weather data for any city using the Open-Meteo API without requiring an API key. It includes geocoding functionality to convert city names to geographic coordinates.
This file contains a suite of tests for the weather tool, checking various scenarios including valid and invalid city inputs, temperature units, and response structure.
Added documentation for the Adventure Log and self-tool building capabilities of Hermes Agent, including installation instructions and test results.
Introduced a self-tool builder skill for Hermes that enables autonomous tool creation, testing, and registration without human intervention. Includes demo tools and tests.
Implemented the mcp-server command for Hermes CLI with options for HTTP transport, host, and port.
Implemented the mcp-server command for the CLI, allowing users to start the Hermes MCP Server with HTTP options.
Implement session analytics for the /stats command, reading from the session database and rendering a summary.
Removed docstrings from several functions to streamline code.
@ygd58 ygd58 closed this Feb 28, 2026
@ygd58 ygd58 reopened this Feb 28, 2026
@ygd58 ygd58 closed this Feb 28, 2026
@maradona-vibrantic

Copy link
Copy Markdown

Retrospective review summary (posting here per request):

Verdict at review time: Request Changes

  • Critical: hermes_cli/commands.py:50 had a stray markdown fence that caused a Python syntax error (SyntaxError: invalid syntax).
  • Minor: hermes_cli/commands.py:8 imported print_stats but did not use it.

Checks run at the time:

  • python -m py_compile hermes_cli/commands.py hermes_cli/stats.py gateway/mcp_server.py (failed on commands.py line 50)
  • pytest -q tests/test_mcp_server.py tests/test_weather.py (passed)

If useful, I can still open a follow-up issue with this audit trail.

ttiger-afk pushed a commit to ttiger-afk/hermes-agent that referenced this pull request Jun 28, 2026
…56 on complete_task

Gate rejects NULL/empty/invalid JSON/empty object results.
Canonical JSON serialization for reproducible SHA-256.
Both UPDATE statements write result_sha256 alongside result.
Fixes Issue NousResearch#154 — Canary A result=NULL bypass.
ttiger-afk added a commit to ttiger-afk/hermes-agent that referenced this pull request Jun 29, 2026
- Remove auto-generation of result from summary (_auto fallback)
- Fix ensure_ascii=False in both _validate_completion_result and
  _canonical_result_sha256 for cross-node hash consistency
- Add 11 tests: null/empty/{}/invalid JSON all rejected
- Unicode result hash matches canonical rule (ensure_ascii=False)
- Writer/Reader/SG now produce identical SHA-256 for results
- Issue NousResearch#154
teddyjfpender added a commit to teddyjfpender/superforecasting-agent that referenced this pull request Jun 30, 2026
…m (sync + async)

Port of NousResearch/hermes-agent 35a0803, same truncate-and-store family as web_extract. The forecaster
fans out delegate_task(background=true) research subagents whose tens-of-KB summaries fold back into the parent
context, risking the compression-429 death spiral. Each summary is now capped against the parent's remaining
headroom split across the batch, full text spilled to cache/delegation (read_file-able). FORK-CRITICAL: applied
on BOTH the sync results.sort path AND the async background re-entry rail (task NousResearch#154 session_key routing) — the
upstream sync-only hook would have missed the fork's dominant delegation mode. New test (8). config keeps the
fork's child_timeout_seconds=600.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
victor-kyriazakos added a commit to victor-kyriazakos/hermes-agent that referenced this pull request Jul 27, 2026
…s_text, carry live per-tool phrase on typing frames (QA-1)

Native Slack shows dynamic assistant-status text ('Finding answers…',
'is running pytest…') because SlackAdapter sets supports_status_text=True
and renders the set_status_text() phrase in send_typing. The relay lane
advertised nothing, so run.py's live-status lane never fed it phrases and
the connector fell back to the static default.

- supports_status_text: descriptor-gated property (Slack only; other
  fronted platforms keep textless bubbles)
- send_typing: carry the stashed phrase as the typing op's content; omit
  when unset (empty string is Slack's explicit clear, reserved for
  stop_typing). Connector already renders content via
  assistant.threads.setStatus (NousResearch#154).
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
…s_text, carry live per-tool phrase on typing frames (QA-1)

Native Slack shows dynamic assistant-status text ('Finding answers…',
'is running pytest…') because SlackAdapter sets supports_status_text=True
and renders the set_status_text() phrase in send_typing. The relay lane
advertised nothing, so run.py's live-status lane never fed it phrases and
the connector fell back to the static default.

- supports_status_text: descriptor-gated property (Slack only; other
  fronted platforms keep textless bubbles)
- send_typing: carry the stashed phrase as the typing op's content; omit
  when unset (empty string is Slack's explicit clear, reserved for
  stop_typing). Connector already renders content via
  assistant.threads.setStatus (NousResearch#154).
33hodl pushed a commit to 33hodl/hermes-agent that referenced this pull request Aug 12, 2026
…s_text, carry live per-tool phrase on typing frames (QA-1)

Native Slack shows dynamic assistant-status text ('Finding answers…',
'is running pytest…') because SlackAdapter sets supports_status_text=True
and renders the set_status_text() phrase in send_typing. The relay lane
advertised nothing, so run.py's live-status lane never fed it phrases and
the connector fell back to the static default.

- supports_status_text: descriptor-gated property (Slack only; other
  fronted platforms keep textless bubbles)
- send_typing: carry the stashed phrase as the typing op's content; omit
  when unset (empty string is Slack's explicit clear, reserved for
  stop_typing). Connector already renders content via
  assistant.threads.setStatus (NousResearch#154).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants