feat(token-viz): Phase 1 — token budget panel with color bar and breakdown table
This commit is contained in:
45
gui_2.py
45
gui_2.py
@@ -296,6 +296,8 @@ class App:
|
||||
self._token_budget_current = 0
|
||||
self._token_budget_limit = 0
|
||||
self._gemini_cache_text = ""
|
||||
self._last_stable_md: str = ''
|
||||
self._token_stats: dict = {}
|
||||
self.ui_disc_truncate_pairs: int = 2
|
||||
self.ui_auto_scroll_comms = True
|
||||
self.ui_auto_scroll_tool_calls = True
|
||||
@@ -552,6 +554,7 @@ class App:
|
||||
start_time = time.time()
|
||||
try:
|
||||
md, path, file_items, stable_md, disc_text = self._do_generate()
|
||||
self._last_stable_md = stable_md
|
||||
self.last_md = md
|
||||
self.last_md_path = path
|
||||
self.last_file_items = file_items
|
||||
@@ -1222,6 +1225,7 @@ class App:
|
||||
"""Logic for the 'Gen + Send' action."""
|
||||
try:
|
||||
md, path, file_items, stable_md, disc_text = self._do_generate()
|
||||
self._last_stable_md = stable_md
|
||||
self.last_md = md
|
||||
self.last_md_path = path
|
||||
self.last_file_items = file_items
|
||||
@@ -1373,6 +1377,7 @@ class App:
|
||||
self._token_budget_pct = stats.get("percentage", 0.0) / 100.0
|
||||
self._token_budget_current = stats.get("current", 0)
|
||||
self._token_budget_limit = stats.get("limit", 0)
|
||||
self._token_stats = stats
|
||||
except Exception:
|
||||
pass
|
||||
threading.Thread(target=fetch_stats, daemon=True).start()
|
||||
@@ -2720,11 +2725,47 @@ class App:
|
||||
if usage["cache_read_input_tokens"]:
|
||||
imgui.text_colored(C_LBL, f" Cache Read: {usage['cache_read_input_tokens']:,} Creation: {usage['cache_creation_input_tokens']:,}")
|
||||
imgui.text("Token Budget:")
|
||||
imgui.progress_bar(self._token_budget_pct, imgui.ImVec2(-1, 0), f"{self._token_budget_current:,} / {self._token_budget_limit:,}")
|
||||
imgui.separator()
|
||||
imgui.text("Token Budget")
|
||||
self._render_token_budget_panel()
|
||||
if self._gemini_cache_text:
|
||||
imgui.text_colored(C_SUB, self._gemini_cache_text)
|
||||
|
||||
def _render_message_panel(self) -> None:
|
||||
def _render_token_budget_panel(self) -> None:
|
||||
stats = self._token_stats
|
||||
if not stats:
|
||||
imgui.text_disabled("Token stats unavailable")
|
||||
return
|
||||
pct = stats.get("utilization_pct", 0.0)
|
||||
current = stats.get("estimated_prompt_tokens", 0)
|
||||
limit = stats.get("max_prompt_tokens", 0)
|
||||
headroom = stats.get("headroom_tokens", 0)
|
||||
if pct < 50.0:
|
||||
color = imgui.ImVec4(0.2, 0.8, 0.2, 1.0)
|
||||
elif pct < 80.0:
|
||||
color = imgui.ImVec4(1.0, 0.8, 0.0, 1.0)
|
||||
else:
|
||||
color = imgui.ImVec4(1.0, 0.2, 0.2, 1.0)
|
||||
imgui.push_style_color(imgui.Col_.plot_histogram, color)
|
||||
imgui.progress_bar(pct / 100.0, imgui.ImVec2(-1, 0), f"{pct:.1f}%")
|
||||
imgui.pop_style_color()
|
||||
imgui.text_disabled(f"{current:,} / {limit:,} tokens ({headroom:,} remaining)")
|
||||
sys_tok = stats.get("system_tokens", 0)
|
||||
tool_tok = stats.get("tools_tokens", 0)
|
||||
hist_tok = stats.get("history_tokens", 0)
|
||||
total_tok = sys_tok + tool_tok + hist_tok or 1
|
||||
if imgui.begin_table("token_breakdown", 3, imgui.TableFlags_.borders_inner_h | imgui.TableFlags_.sizing_fixed_fit):
|
||||
imgui.table_setup_column("Component")
|
||||
imgui.table_setup_column("Tokens")
|
||||
imgui.table_setup_column("Pct")
|
||||
imgui.table_headers_row()
|
||||
for lbl, tok in [("System", sys_tok), ("Tools", tool_tok), ("History", hist_tok)]:
|
||||
imgui.table_next_row()
|
||||
imgui.table_set_column_index(0); imgui.text(lbl)
|
||||
imgui.table_set_column_index(1); imgui.text(f"{tok:,}")
|
||||
imgui.table_set_column_index(2); imgui.text(f"{tok / total_tok * 100:.0f}%")
|
||||
imgui.end_table()
|
||||
|
||||
# LIVE indicator
|
||||
is_live = self.ai_status in ["running powershell...", "fetching url...", "searching web...", "powershell done, awaiting AI..."]
|
||||
if is_live:
|
||||
|
||||
Reference in New Issue
Block a user