From d82384441745550ea2c346d394a37e3cb8dd126e Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sat, 7 Mar 2026 10:45:01 -0500 Subject: [PATCH] feat(gui): add dedicated Cache Analytics panel with TTL countdown and clear button --- src/gui_2.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/gui_2.py b/src/gui_2.py index 6500df4..183d16a 100644 --- a/src/gui_2.py +++ b/src/gui_2.py @@ -331,6 +331,8 @@ class App: self._render_provider_panel() if imgui.collapsing_header("Token Budget"): self._render_token_budget_panel() + if imgui.collapsing_header("Cache Analytics"): + self._render_cache_panel() if imgui.collapsing_header("System Prompts"): self._render_system_prompts_panel() @@ -1449,6 +1451,39 @@ class App: imgui.text_disabled("Anthropic: 4-breakpoint ephemeral caching (auto-managed)") imgui.text_disabled(f" {turns} history turns | Cache reads last call: {cache_reads:,}") + def _render_cache_panel(self) -> None: + if self.current_provider != "gemini": + return + if not imgui.collapsing_header("Cache Analytics"): + return + stats = ai_client.get_gemini_cache_stats() + if not stats.get("cache_exists"): + imgui.text_disabled("No active cache") + if imgui.button("Force Cache"): + pass + return + age_sec = stats.get("cache_age_seconds", 0) + ttl_remaining = stats.get("ttl_remaining", 0) + ttl_total = stats.get("ttl_seconds", 3600) + age_str = f"{age_sec/60:.0f}m {age_sec%60:.0f}s" + remaining_str = f"{ttl_remaining/60:.0f}m {ttl_remaining%60:.0f}s" + ttl_pct = (ttl_remaining / ttl_total * 100) if ttl_total > 0 else 0 + imgui.text(f"Age: {age_str}") + imgui.text(f"TTL: {remaining_str} ({ttl_pct:.0f}%)") + color = imgui.ImVec4(0.2, 0.8, 0.2, 1.0) + if ttl_pct < 20: + color = imgui.ImVec4(1.0, 0.2, 0.2, 1.0) + elif ttl_pct < 50: + color = imgui.ImVec4(1.0, 0.8, 0.0, 1.0) + imgui.push_style_color(imgui.Col_.plot_histogram, color) + imgui.progress_bar(ttl_pct / 100.0, imgui.ImVec2(-1, 0), f"{ttl_pct:.0f}%") + imgui.pop_style_color() + if imgui.button("Clear Cache"): + ai_client.cleanup() + self._cache_cleared_timestamp = time.time() + if hasattr(self, '_cache_cleared_timestamp') and time.time() - self._cache_cleared_timestamp < 5: + imgui.text_colored(imgui.ImVec4(0.2, 1.0, 0.2, 1.0), "Cache cleared - will rebuild on next request") + def _render_message_panel(self) -> None: # LIVE indicator is_live = self.ai_status in ["running powershell...", "fetching url...", "searching web...", "powershell done, awaiting AI..."]