Skip to content
Open
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
7 changes: 6 additions & 1 deletion agent/insights.py
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,9 @@ def format_terminal(self, report: Dict) -> str:
lines.append(f" Sessions: {o['total_sessions']:<12} Messages: {o['total_messages']:,}")
lines.append(f" Tool calls: {o['total_tool_calls']:<12,} User messages: {o['user_messages']:,}")
lines.append(f" Input tokens: {o['total_input_tokens']:<12,} Output tokens: {o['total_output_tokens']:,}")
cache_total = (o.get('total_cache_read_tokens') or 0) + (o.get('total_cache_write_tokens') or 0)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This restores cache-token output that current main deliberately removed in #11477 (e33cb65a9) because cache metrics were unreliable. Current tests retain the no-cache display contract; please reconcile this change with that policy before reintroducing the value.

if cache_total:
lines.append(f" Cache tokens: {cache_total:<12,} (read: {o.get('total_cache_read_tokens') or 0:,} / write: {o.get('total_cache_write_tokens') or 0:,})")
lines.append(f" Total tokens: {o['total_tokens']:,}")
if o["total_hours"] > 0:
lines.append(f" Active time: ~{_format_duration(o['total_hours'] * 3600):<11} Avg session: ~{_format_duration(o['avg_session_duration'])}")
Expand Down Expand Up @@ -877,7 +880,9 @@ def format_gateway(self, report: Dict) -> str:

# Overview
lines.append(f"**Sessions:** {o['total_sessions']} | **Messages:** {o['total_messages']:,} | **Tool calls:** {o['total_tool_calls']:,}")
lines.append(f"**Tokens:** {o['total_tokens']:,} (in: {o['total_input_tokens']:,} / out: {o['total_output_tokens']:,})")
cache_total = (o.get('total_cache_read_tokens') or 0) + (o.get('total_cache_write_tokens') or 0)
cache_part = f" / cache: {cache_total:,}" if cache_total else ""
lines.append(f"**Tokens:** {o['total_tokens']:,} (in: {o['total_input_tokens']:,} / out: {o['total_output_tokens']:,}{cache_part})")
if o["total_hours"] > 0:
lines.append(f"**Active time:** ~{_format_duration(o['total_hours'] * 3600)} | **Avg session:** ~{_format_duration(o['avg_session_duration'])}")
lines.append("")
Expand Down
71 changes: 71 additions & 0 deletions tests/agent/test_insights.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,77 @@ def test_gateway_format_shows_models(self, populated_db):
assert "sessions" in text


# =========================================================================
# Cache token display (issue #18615)
# =========================================================================

class TestCacheTokenDisplay:
def _make_db_with_cache(self, db):
"""Helper: create a session with significant cache tokens."""
db.create_session(session_id="s_cache", source="cli", model="claude-sonnet")
db.update_token_counts(
"s_cache",
input_tokens=2000,
output_tokens=800,
cache_read_tokens=50000,
cache_write_tokens=10000,
)
db._conn.commit()
return db

def test_terminal_format_shows_cache_when_present(self, db):
"""Terminal format must include cache token line when cache > 0."""
self._make_db_with_cache(db)
engine = InsightsEngine(db)
report = engine.generate(days=30)
text = engine.format_terminal(report)

assert "Cache tokens" in text
assert "50,000" in text or "60,000" in text # read or total

def test_gateway_format_shows_cache_when_present(self, db):
"""Gateway format must include cache in token breakdown when cache > 0."""
self._make_db_with_cache(db)
engine = InsightsEngine(db)
report = engine.generate(days=30)
text = engine.format_gateway(report)

assert "cache:" in text.lower()

def test_terminal_format_hides_cache_when_zero(self, db):
"""Terminal format must NOT show cache line when all cache tokens are 0."""
db.create_session(session_id="s_nocache", source="cli", model="gpt-4o")
db.update_token_counts("s_nocache", input_tokens=1000, output_tokens=500)
db._conn.commit()

engine = InsightsEngine(db)
report = engine.generate(days=30)
text = engine.format_terminal(report)

assert "Cache tokens" not in text

def test_gateway_format_hides_cache_when_zero(self, db):
"""Gateway format must NOT mention cache when all cache tokens are 0."""
db.create_session(session_id="s_nocache", source="cli", model="gpt-4o")
db.update_token_counts("s_nocache", input_tokens=1000, output_tokens=500)
db._conn.commit()

engine = InsightsEngine(db)
report = engine.generate(days=30)
text = engine.format_gateway(report)

assert "cache" not in text.lower()

def test_total_tokens_include_cache(self, db):
"""total_tokens must equal input + output + cache_read + cache_write."""
self._make_db_with_cache(db)
engine = InsightsEngine(db)
report = engine.generate(days=30)
o = report["overview"]

assert o["total_tokens"] == 2000 + 800 + 50000 + 10000


# =========================================================================
# Edge cases
# =========================================================================
Expand Down