Private
Public Access
0
0

feat(gui): Implement per-response token metrics and AI discussion compression

- Display token metrics (input/output/cache) per response in Discussion Hub.
- Add total Discussion Token usage in the panel header.
- Implement 'Compress' feature to intelligently summarize and replace exhausted discussion histories using an AI subagent.
This commit is contained in:
2026-06-02 01:36:57 -04:00
parent b3b9baf91f
commit 5b7b818ed2
5 changed files with 106 additions and 24 deletions
+36 -11
View File
@@ -3416,17 +3416,29 @@ def render_discussion_entry(app: App, entry: dict, index: int) -> None:
imgui.same_line()
if imgui.button("[Edit]" if read_mode else "[Read]"): entry["read_mode"] = not read_mode
ts_str = entry.get("ts", "")
if ts_str:
imgui.same_line(); imgui.text_colored(vec4(120, 120, 100), str(ts_str)); e_dt = project_manager.parse_ts(ts_str)
if e_dt:
e_unix, next_unix = e_dt.timestamp(), float('inf')
if index + 1 < len(app.disc_entries):
n_ts = app.disc_entries[index+1].get("ts", ""); n_dt = project_manager.parse_ts(n_ts)
if n_dt: next_unix = n_dt.timestamp()
injected = [f for f in app.files if hasattr(f, 'injected_at') and f.injected_at and e_unix <= f.injected_at < next_unix]
if injected:
imgui.same_line(); imgui.text_colored(vec4(100, 255, 100), f"[{len(injected)}+]")
if imgui.is_item_hovered(): imgui.set_tooltip("Files injected at this point:\n" + "\n".join([f.path for f in injected]))
usage = entry.get("usage", {})
if ts_str or usage:
imgui.same_line()
if ts_str:
imgui.text_colored(vec4(120, 120, 100), str(ts_str))
e_dt = project_manager.parse_ts(ts_str)
if e_dt:
e_unix, next_unix = e_dt.timestamp(), float('inf')
if index + 1 < len(app.disc_entries):
n_ts = app.disc_entries[index+1].get("ts", ""); n_dt = project_manager.parse_ts(n_ts)
if n_dt: next_unix = n_dt.timestamp()
injected = [f for f in app.files if hasattr(f, 'injected_at') and f.injected_at and e_unix <= f.injected_at < next_unix]
if injected:
imgui.same_line(); imgui.text_colored(vec4(100, 255, 100), f"[{len(injected)}+]")
if imgui.is_item_hovered(): imgui.set_tooltip("Files injected at this point:\n" + "\n".join([f.path for f in injected]))
if usage:
inp = usage.get("input_tokens", 0)
out = usage.get("output_tokens", 0)
cache = usage.get("cache_read_input_tokens", 0)
usage_str = f" in:{inp} out:{out}"
if cache: usage_str += f" cache:{cache}"
imgui.same_line()
imgui.text_colored(vec4(100, 150, 180), usage_str)
if collapsed:
imgui.same_line()
if imgui.button("Ins"): app.disc_entries.insert(index, {"role": "User", "content": "", "collapsed": True, "ts": project_manager.now_ts()})
@@ -3794,6 +3806,8 @@ def render_discussion_entry_controls(app: App) -> None:
if imgui.button("Clear All"): app.disc_entries.clear()
imgui.same_line()
if imgui.button("Save"): app._flush_to_project(); app._flush_to_config(); models.save_config(app.config); app.ai_status = "discussion saved"
imgui.same_line()
if imgui.button("Compress"): app.controller._handle_compress_discussion()
_, app.ui_auto_add_history = imgui.checkbox("Auto-add message & response to history", app.ui_auto_add_history)
imgui.text("Keep Pairs:"); imgui.same_line(); imgui.set_next_item_width(80)
ch, app.ui_disc_truncate_pairs = imgui.input_int("##trunc_pairs", app.ui_disc_truncate_pairs, 1)
@@ -3806,6 +3820,17 @@ def render_discussion_entry_controls(app: App) -> None:
def render_discussion_metadata(app: App) -> None:
disc_data = app.project.get("discussion", {}).get("discussions", {}).get(app.active_discussion, {})
git_commit, last_updated = disc_data.get("git_commit", ""), disc_data.get("last_updated", "")
total_in, total_out, total_cache = 0, 0, 0
for entry in app.disc_entries:
if "usage" in entry:
total_in += entry["usage"].get("input_tokens", 0)
total_out += entry["usage"].get("output_tokens", 0)
total_cache += entry["usage"].get("cache_read_input_tokens", 0)
if total_in > 0 or total_out > 0:
imgui.text_colored(vec4(100, 150, 180), f"Discussion Tokens: {total_in} In | {total_out} Out | {total_cache} Cache")
imgui.separator()
imgui.text_colored(C_LBL, "commit:"); imgui.same_line()
render_selectable_label(app, 'git_commit_val', git_commit[:12] if git_commit else '(none)', width=100, color=(C_IN if git_commit else C_LBL))
imgui.same_line()