fix(gui): fix missing token stats and improve standalone monologue rendering

This commit is contained in:
2026-03-15 15:57:08 -04:00
parent 226ffdbd2a
commit 5285bc68f9
2 changed files with 38 additions and 11 deletions

View File

@@ -1458,9 +1458,22 @@ class AppController:
if kind == "response" and "usage" in payload: if kind == "response" and "usage" in payload:
u = payload["usage"] u = payload["usage"]
for k in ["input_tokens", "output_tokens", "cache_read_input_tokens", "cache_creation_input_tokens", "total_tokens"]: inp = u.get("input_tokens", u.get("prompt_tokens", 0))
if k in u: out = u.get("output_tokens", u.get("completion_tokens", 0))
self.session_usage[k] += u.get(k, 0) or 0 cache_read = u.get("cache_read_input_tokens", 0)
cache_create = u.get("cache_creation_input_tokens", 0)
total = u.get("total_tokens", 0)
# Store normalized usage back in payload for history rendering
u["input_tokens"] = inp
u["output_tokens"] = out
u["cache_read_input_tokens"] = cache_read
self.session_usage["input_tokens"] += inp
self.session_usage["output_tokens"] += out
self.session_usage["cache_read_input_tokens"] += cache_read
self.session_usage["cache_creation_input_tokens"] += cache_create
self.session_usage["total_tokens"] += total
input_t = u.get("input_tokens", 0) input_t = u.get("input_tokens", 0)
output_t = u.get("output_tokens", 0) output_t = u.get("output_tokens", 0)
model = payload.get("model", "unknown") model = payload.get("model", "unknown")

View File

@@ -326,22 +326,31 @@ class App:
if is_nerv: imgui.pop_style_color() if is_nerv: imgui.pop_style_color()
# ---------------------------------------------------------------- gui # ---------------------------------------------------------------- gui
def _render_thinking_trace(self, segments: list[dict], entry_index: int) -> None: def _render_thinking_trace(self, segments: list[dict], entry_index: int, is_standalone: bool = False) -> None:
if not segments: if not segments:
return return
imgui.push_style_color(imgui.Col_.child_bg, vec4(40, 35, 25, 180)) imgui.push_style_color(imgui.Col_.child_bg, vec4(40, 35, 25, 180))
imgui.push_style_color(imgui.Col_.text, vec4(200, 200, 150)) imgui.push_style_color(imgui.Col_.text, vec4(200, 200, 150))
imgui.indent() imgui.indent()
header_label = f"Monologue ({len(segments)} traces)###thinking_header_{entry_index}" show_content = True
if imgui.collapsing_header(header_label): if not is_standalone:
imgui.begin_child(f"thinking_content_{entry_index}", imgui.ImVec2(0, 80), True) header_label = f"Monologue ({len(segments)} traces)###thinking_header_{entry_index}"
show_content = imgui.collapsing_header(header_label)
if show_content:
h = 150 if is_standalone else 100
imgui.begin_child(f"thinking_content_{entry_index}", imgui.ImVec2(0, h), True)
for idx, seg in enumerate(segments): for idx, seg in enumerate(segments):
content = seg.get("content", "") content = seg.get("content", "")
marker = seg.get("marker", "thinking") marker = seg.get("marker", "thinking")
imgui.push_id(f"think_{entry_index}_{idx}") imgui.push_id(f"think_{entry_index}_{idx}")
imgui.text_colored(vec4(180, 150, 80), f"[{marker}]") imgui.text_colored(vec4(180, 150, 80), f"[{marker}]")
imgui.same_line() if self.ui_word_wrap:
imgui.text_colored(vec4(200, 200, 150), content) imgui.push_text_wrap_pos(imgui.get_content_region_avail().x)
imgui.text_colored(vec4(200, 200, 150), content)
imgui.pop_text_wrap_pos()
else:
imgui.text_colored(vec4(200, 200, 150), content)
imgui.pop_id() imgui.pop_id()
imgui.separator() imgui.separator()
imgui.end_child() imgui.end_child()
@@ -2280,11 +2289,16 @@ def hello():
imgui.same_line() imgui.same_line()
preview = entry["content"].replace("\\n", " ")[:60] preview = entry["content"].replace("\\n", " ")[:60]
if len(entry["content"]) > 60: preview += "..." if len(entry["content"]) > 60: preview += "..."
if not preview.strip() and entry.get("thinking_segments"):
preview = entry["thinking_segments"][0]["content"].replace("\\n", " ")[:60]
if len(entry["thinking_segments"][0]["content"]) > 60: preview += "..."
imgui.text_colored(vec4(160, 160, 150), preview) imgui.text_colored(vec4(160, 160, 150), preview)
if not collapsed: if not collapsed:
thinking_segments = entry.get("thinking_segments", []) thinking_segments = entry.get("thinking_segments", [])
has_content = bool(entry.get("content", "").strip())
is_standalone = bool(thinking_segments) and not has_content
if thinking_segments: if thinking_segments:
self._render_thinking_trace(thinking_segments, i) self._render_thinking_trace(thinking_segments, i, is_standalone=is_standalone)
if read_mode: if read_mode:
content = entry["content"] content = entry["content"]
if content.strip(): if content.strip():
@@ -2943,7 +2957,7 @@ def hello():
text_content = payload.get("text", "") text_content = payload.get("text", "")
segments, parsed_response = thinking_parser.parse_thinking_trace(text_content) segments, parsed_response = thinking_parser.parse_thinking_trace(text_content)
if segments: if segments:
self._render_thinking_trace([{"content": s.content, "marker": s.marker} for s in segments], i) self._render_thinking_trace([{"content": s.content, "marker": s.marker} for s in segments], i, is_standalone=not bool(parsed_response.strip()))
if parsed_response: if parsed_response:
self._render_heavy_text("text", parsed_response, idx_str) self._render_heavy_text("text", parsed_response, idx_str)