From fe331ed9bdc541377308c6447b80847b82f06721 Mon Sep 17 00:00:00 2001 From: InB4DevOps Date: Thu, 19 Mar 2026 23:53:51 +0100 Subject: [PATCH] fix: Reset token counters on new session for accurate usage display (#2099) --- cli.py | 1 + run_agent.py | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/cli.py b/cli.py index d576387b..a047471b 100755 --- a/cli.py +++ b/cli.py @@ -2733,6 +2733,7 @@ class HermesCLI: if self.agent: self.agent.session_id = self.session_id self.agent.session_start = self.session_start + self.agent.reset_session_state() if hasattr(self.agent, "_last_flushed_db_idx"): self.agent._last_flushed_db_idx = 0 if hasattr(self.agent, "_todo_store"): diff --git a/run_agent.py b/run_agent.py index 878188f9..b035ee0e 100644 --- a/run_agent.py +++ b/run_agent.py @@ -1016,6 +1016,43 @@ class AIAgent: print(f"📊 Context limit: {self.context_compressor.context_length:,} tokens (compress at {int(compression_threshold*100)}% = {self.context_compressor.threshold_tokens:,})") else: print(f"📊 Context limit: {self.context_compressor.context_length:,} tokens (auto-compression disabled)") + + def reset_session_state(self): + """Reset all session-scoped token counters to 0 for a fresh session. + + This method encapsulates the reset logic for all session-level metrics + including: + - Token usage counters (input, output, total, prompt, completion) + - Cache read/write tokens + - API call count + - Reasoning tokens + - Estimated cost tracking + - Context compressor internal counters + + The method safely handles optional attributes (e.g., context compressor) + using ``hasattr`` checks. + + This keeps the counter reset logic DRY and maintainable in one place + rather than scattering it across multiple methods. + """ + # Token usage counters + self.session_total_tokens = 0 + self.session_input_tokens = 0 + self.session_output_tokens = 0 + self.session_prompt_tokens = 0 + self.session_completion_tokens = 0 + self.session_cache_read_tokens = 0 + self.session_cache_write_tokens = 0 + self.session_reasoning_tokens = 0 + self.session_api_calls = 0 + self.session_estimated_cost_usd = 0.0 + self.session_cost_status = "unknown" + self.session_cost_source = "none" + + # Context compressor internal counters (if present) + if hasattr(self, "context_compressor") and self.context_compressor: + self.context_compressor.last_prompt_tokens = 0 + self.context_compressor.last_completion_tokens = 0 @staticmethod def _safe_print(*args, **kwargs):