Compare commits
3 Commits
d6cdbf21d7
...
f72b081154
| Author | SHA1 | Date | |
|---|---|---|---|
| f72b081154 | |||
| 6f96f71917 | |||
| 9aea9b6210 |
@@ -50,7 +50,7 @@ This file tracks all major tracks for the project. Each track has its own detail
|
|||||||
9. [x] **Track: Tool Usage Analytics**
|
9. [x] **Track: Tool Usage Analytics**
|
||||||
*Link: [./tracks/tool_usage_analytics_20260306/](./tracks/tool_usage_analytics_20260306/)*
|
*Link: [./tracks/tool_usage_analytics_20260306/](./tracks/tool_usage_analytics_20260306/)*
|
||||||
|
|
||||||
10. [ ] **Track: Session Insights & Efficiency Scores**
|
10. [x] **Track: Session Insights & Efficiency Scores**
|
||||||
*Link: [./tracks/session_insights_20260306/](./tracks/session_insights_20260306/)*
|
*Link: [./tracks/session_insights_20260306/](./tracks/session_insights_20260306/)*
|
||||||
|
|
||||||
11. [ ] **Track: Track Progress Visualization**
|
11. [ ] **Track: Track Progress Visualization**
|
||||||
|
|||||||
@@ -147,6 +147,8 @@ class AppController:
|
|||||||
self._tool_log: List[Dict[str, Any]] = []
|
self._tool_log: List[Dict[str, Any]] = []
|
||||||
self._tool_stats: Dict[str, Dict[str, Any]] = {} # {tool_name: {"count": 0, "total_time_ms": 0.0, "failures": 0}}
|
self._tool_stats: Dict[str, Dict[str, Any]] = {} # {tool_name: {"count": 0, "total_time_ms": 0.0, "failures": 0}}
|
||||||
self._cached_cache_stats: Dict[str, Any] = {} # Pre-computed cache stats for GUI
|
self._cached_cache_stats: Dict[str, Any] = {} # Pre-computed cache stats for GUI
|
||||||
|
self._token_history: List[Dict[str, Any]] = [] # Token usage over time [{"time": t, "input": n, "output": n, "model": s}, ...]
|
||||||
|
self._session_start_time: float = time.time() # For calculating burn rate
|
||||||
self._comms_log: List[Dict[str, Any]] = []
|
self._comms_log: List[Dict[str, Any]] = []
|
||||||
self.session_usage: Dict[str, Any] = {
|
self.session_usage: Dict[str, Any] = {
|
||||||
"input_tokens": 0,
|
"input_tokens": 0,
|
||||||
@@ -961,6 +963,15 @@ class AppController:
|
|||||||
for k in ["input_tokens", "output_tokens", "cache_read_input_tokens", "cache_creation_input_tokens", "total_tokens"]:
|
for k in ["input_tokens", "output_tokens", "cache_read_input_tokens", "cache_creation_input_tokens", "total_tokens"]:
|
||||||
if k in u:
|
if k in u:
|
||||||
self.session_usage[k] += u.get(k, 0) or 0
|
self.session_usage[k] += u.get(k, 0) or 0
|
||||||
|
input_t = u.get("input_tokens", 0)
|
||||||
|
output_t = u.get("output_tokens", 0)
|
||||||
|
model = payload.get("model", "unknown")
|
||||||
|
self._token_history.append({
|
||||||
|
"time": time.time(),
|
||||||
|
"input": input_t,
|
||||||
|
"output": output_t,
|
||||||
|
"model": model
|
||||||
|
})
|
||||||
|
|
||||||
if kind in ("tool_result", "tool_call"):
|
if kind in ("tool_result", "tool_call"):
|
||||||
role = "Tool" if kind == "tool_result" else "Vendor API"
|
role = "Tool" if kind == "tool_result" else "Vendor API"
|
||||||
@@ -1753,6 +1764,28 @@ class AppController:
|
|||||||
ai_client.cleanup()
|
ai_client.cleanup()
|
||||||
self._update_cached_stats()
|
self._update_cached_stats()
|
||||||
|
|
||||||
|
def get_session_insights(self) -> Dict[str, Any]:
|
||||||
|
from src import cost_tracker
|
||||||
|
total_input = sum(e["input"] for e in self._token_history)
|
||||||
|
total_output = sum(e["output"] for e in self._token_history)
|
||||||
|
total_tokens = total_input + total_output
|
||||||
|
elapsed_min = (time.time() - self._session_start_time) / 60.0 if self._token_history else 0
|
||||||
|
burn_rate = total_tokens / elapsed_min if elapsed_min > 0 else 0
|
||||||
|
session_cost = cost_tracker.estimate_cost("gemini-2.5-flash", total_input, total_output)
|
||||||
|
completed = sum(1 for t in self.active_tickets if t.get("status") == "complete")
|
||||||
|
efficiency = total_tokens / completed if completed > 0 else 0
|
||||||
|
return {
|
||||||
|
"total_tokens": total_tokens,
|
||||||
|
"total_input": total_input,
|
||||||
|
"total_output": total_output,
|
||||||
|
"elapsed_min": elapsed_min,
|
||||||
|
"burn_rate": burn_rate,
|
||||||
|
"session_cost": session_cost,
|
||||||
|
"completed_tickets": completed,
|
||||||
|
"efficiency": efficiency,
|
||||||
|
"call_count": len(self._token_history)
|
||||||
|
}
|
||||||
|
|
||||||
def _flush_to_project(self) -> None:
|
def _flush_to_project(self) -> None:
|
||||||
proj = self.project
|
proj = self.project
|
||||||
proj.setdefault("output", {})["output_dir"] = self.ui_output_dir
|
proj.setdefault("output", {})["output_dir"] = self.ui_output_dir
|
||||||
|
|||||||
14
src/gui_2.py
14
src/gui_2.py
@@ -333,6 +333,7 @@ class App:
|
|||||||
self._render_token_budget_panel()
|
self._render_token_budget_panel()
|
||||||
self._render_cache_panel()
|
self._render_cache_panel()
|
||||||
self._render_tool_analytics_panel()
|
self._render_tool_analytics_panel()
|
||||||
|
self._render_session_insights_panel()
|
||||||
if imgui.collapsing_header("System Prompts"):
|
if imgui.collapsing_header("System Prompts"):
|
||||||
self._render_system_prompts_panel()
|
self._render_system_prompts_panel()
|
||||||
|
|
||||||
@@ -1509,6 +1510,19 @@ class App:
|
|||||||
imgui.text("0%")
|
imgui.text("0%")
|
||||||
imgui.end_table()
|
imgui.end_table()
|
||||||
|
|
||||||
|
def _render_session_insights_panel(self) -> None:
|
||||||
|
if not imgui.collapsing_header("Session Insights"):
|
||||||
|
return
|
||||||
|
insights = self.controller.get_session_insights()
|
||||||
|
imgui.text(f"Total Tokens: {insights.get('total_tokens', 0):,}")
|
||||||
|
imgui.text(f"API Calls: {insights.get('call_count', 0)}")
|
||||||
|
imgui.text(f"Burn Rate: {insights.get('burn_rate', 0):.0f} tokens/min")
|
||||||
|
imgui.text(f"Session Cost: ${insights.get('session_cost', 0):.4f}")
|
||||||
|
completed = insights.get('completed_tickets', 0)
|
||||||
|
efficiency = insights.get('efficiency', 0)
|
||||||
|
imgui.text(f"Completed: {completed}")
|
||||||
|
imgui.text(f"Tokens/Ticket: {efficiency:.0f}" if efficiency > 0 else "Tokens/Ticket: N/A")
|
||||||
|
|
||||||
def _render_message_panel(self) -> None:
|
def _render_message_panel(self) -> None:
|
||||||
# LIVE indicator
|
# LIVE indicator
|
||||||
is_live = self.ai_status in ["running powershell...", "fetching url...", "searching web...", "powershell done, awaiting AI..."]
|
is_live = self.ai_status in ["running powershell...", "fetching url...", "searching web...", "powershell done, awaiting AI..."]
|
||||||
|
|||||||
Reference in New Issue
Block a user