diff --git a/app.py b/app.py index ae89640..29ef1b7 100644 --- a/app.py +++ b/app.py @@ -711,7 +711,8 @@ def finalize_token_window(window: Dict[str, Any]): input_tokens = window.get("input_tokens", 0) cached_tokens = window.get("cached_input_tokens", 0) if input_tokens > 0: - window["cache_hit_percent"] = round(cached_tokens * 100 / input_tokens, 1) + cache_hit_percent = cached_tokens * 100 / input_tokens + window["cache_hit_percent"] = round(max(0, min(100, cache_hit_percent)), 1) def recent_session_files(session_dirs: list, limit: int) -> list: diff --git a/tests/test_vibe_status.py b/tests/test_vibe_status.py index 1f94b4e..18ae319 100644 --- a/tests/test_vibe_status.py +++ b/tests/test_vibe_status.py @@ -625,6 +625,34 @@ def test_compute_local_token_usage_clamps_negative_token_counts(self): self.assertEqual(window_24h["reasoning_output_tokens"], 0) self.assertEqual(window_24h["total_tokens"], 0) + def test_compute_local_token_usage_clamps_cache_hit_percent(self): + codex_home = Path(self.tmpdir.name) / ".codex" + session_dir = codex_home / "sessions" + session_dir.mkdir(parents=True) + now = datetime(2026, 5, 29, 10, 0, 0, tzinfo=timezone.utc) + session_file = session_dir / "cache.jsonl" + event = { + "timestamp": (now - timedelta(hours=1)).isoformat().replace("+00:00", "Z"), + "type": "event_msg", + "payload": { + "type": "token_count", + "info": { + "last_token_usage": { + "input_tokens": 10, + "cached_input_tokens": 25, + "output_tokens": 0, + "reasoning_output_tokens": 0, + "total_tokens": 10, + }, + }, + }, + } + session_file.write_text(json.dumps(event) + "\n", encoding="utf-8") + + usage = app.compute_local_token_usage(codex_home=codex_home, now=now) + + self.assertEqual(usage["windows"]["24h"]["cache_hit_percent"], 100.0) + def test_compute_local_token_usage_respects_session_file_limit(self): codex_home = Path(self.tmpdir.name) / ".codex" session_dir = codex_home / "sessions"