From e8087424506c2fca2950f98f7fce3efea4ac179f Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Wed, 2 Sep 2026 21:43:57 -0700 Subject: [PATCH] refactor(hermes_cli/web_routers/analytics): _rows query helper, _AUX_SUMMED_KEYS table, comprehension for model cards --- hermes_cli/web_routers/analytics.py | 54 +++++++++++++---------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/hermes_cli/web_routers/analytics.py b/hermes_cli/web_routers/analytics.py index d42257e230..95927dc044 100644 --- a/hermes_cli/web_routers/analytics.py +++ b/hermes_cli/web_routers/analytics.py @@ -72,13 +72,17 @@ async def update_config_raw(body: RawConfigUpdate, profile: Optional[str] = None raise HTTPException(status_code=400, detail=f"Invalid YAML: {e}") +def _rows(db, sql: str, cutoff: float) -> List[Dict[str, Any]]: + return [dict(r) for r in db._conn.execute(sql, (cutoff,)).fetchall()] + + def _get_usage_analytics(days: int = 30, profile: Optional[str] = None): from agent.insights import InsightsEngine db = _open_session_db_for_profile(profile, read_only=True) try: cutoff = time.time() - (days * 86400) - cur = db._conn.execute(""" + daily = _rows(db, """ SELECT date(started_at, 'unixepoch') as day, SUM(input_tokens) as input_tokens, SUM(output_tokens) as output_tokens, @@ -90,10 +94,9 @@ def _get_usage_analytics(days: int = 30, profile: Optional[str] = None): SUM(COALESCE(api_call_count, 0)) as api_calls FROM sessions WHERE started_at > ? GROUP BY day ORDER BY day - """, (cutoff,)) - daily = [dict(r) for r in cur.fetchall()] + """, cutoff) - cur2 = db._conn.execute(""" + by_model = _rows(db, """ SELECT model, SUM(input_tokens) as input_tokens, SUM(output_tokens) as output_tokens, @@ -102,15 +105,14 @@ def _get_usage_analytics(days: int = 30, profile: Optional[str] = None): SUM(COALESCE(api_call_count, 0)) as api_calls FROM sessions WHERE started_at > ? AND model IS NOT NULL GROUP BY model ORDER BY SUM(input_tokens) + SUM(output_tokens) DESC - """, (cutoff,)) - by_model = [dict(r) for r in cur2.fetchall()] + """, cutoff) # Fold in auxiliary usage (vision, compression, ...) from session_model_usage. # Aux calls never touch the sessions counters, so this is add-only — no double count. aux_rows = _aux_usage_rows(db, cutoff) by_model = _merge_aux_into_by_model(by_model, aux_rows) - cur3 = db._conn.execute(""" + totals = _rows(db, """ SELECT SUM(input_tokens) as total_input, SUM(output_tokens) as total_output, SUM(cache_read_tokens) as total_cache_read, @@ -120,8 +122,7 @@ def _get_usage_analytics(days: int = 30, profile: Optional[str] = None): COUNT(*) as total_sessions, SUM(COALESCE(api_call_count, 0)) as total_api_calls FROM sessions WHERE started_at > ? - """, (cutoff,)) - totals = dict(cur3.fetchone()) + """, cutoff)[0] usage = InsightsEngine(db).get_usage_breakdown(days=days) return { @@ -214,6 +215,9 @@ def _model_capabilities(provider: str, model_name: str) -> dict: } +_AUX_SUMMED_KEYS = ( + "input_tokens", "output_tokens", "cache_read_tokens", "reasoning_tokens", "estimated_cost", "sessions", "api_calls", +) _MODEL_CARD_KEYS = ( "input_tokens", "output_tokens", "cache_read_tokens", "reasoning_tokens", "estimated_cost", "actual_cost", "sessions", "api_calls", "tool_calls", @@ -227,7 +231,7 @@ def _get_models_analytics(days: int = 30, profile: Optional[str] = None): try: cutoff = time.time() - (days * 86400) - cur = db._conn.execute(""" + raw_rows = _rows(db, """ SELECT model, billing_provider, SUM(input_tokens) as input_tokens, @@ -244,8 +248,7 @@ def _get_models_analytics(days: int = 30, profile: Optional[str] = None): FROM sessions WHERE started_at > ? AND model IS NOT NULL AND model != '' GROUP BY model, billing_provider ORDER BY SUM(input_tokens) + SUM(output_tokens) DESC - """, (cutoff,)) - raw_rows = [dict(r) for r in cur.fetchall()] + """, cutoff) # Aux-only models (dedicated vision/compression) as (model, provider) rows, # keyed like the GROUP BY above, so they appear on the Models page. @@ -253,14 +256,8 @@ def _get_models_analytics(days: int = 30, profile: Optional[str] = None): raw_rows.append({ "model": aux.get("model") or "unknown", "billing_provider": aux.get("billing_provider") or "", - "input_tokens": aux.get("input_tokens") or 0, - "output_tokens": aux.get("output_tokens") or 0, - "cache_read_tokens": aux.get("cache_read_tokens") or 0, - "reasoning_tokens": aux.get("reasoning_tokens") or 0, - "estimated_cost": aux.get("estimated_cost") or 0, + **{key: aux.get(key) or 0 for key in _AUX_SUMMED_KEYS}, "actual_cost": 0, - "sessions": aux.get("sessions") or 0, - "api_calls": aux.get("api_calls") or 0, "tool_calls": 0, "last_used_at": aux.get("last_used_at"), "avg_tokens_per_session": 0, @@ -273,17 +270,17 @@ def _get_models_analytics(days: int = 30, profile: Optional[str] = None): reverse=True, ) - models = [] - for row in rows: - provider = row.get("billing_provider") or "" - models.append({ + models = [ + { "model": row["model"], - "provider": provider, + "provider": row.get("billing_provider") or "", **{key: row[key] for key in _MODEL_CARD_KEYS}, - "capabilities": _model_capabilities(provider, row["model"]), - }) + "capabilities": _model_capabilities(row.get("billing_provider") or "", row["model"]), + } + for row in rows + ] - totals_cur = db._conn.execute(""" + totals = _rows(db, """ SELECT COUNT(DISTINCT model) as distinct_models, SUM(input_tokens) as total_input, SUM(output_tokens) as total_output, @@ -294,8 +291,7 @@ def _get_models_analytics(days: int = 30, profile: Optional[str] = None): COUNT(*) as total_sessions, SUM(COALESCE(api_call_count, 0)) as total_api_calls FROM sessions WHERE started_at > ? AND model IS NOT NULL AND model != '' - """, (cutoff,)) - totals = dict(totals_cur.fetchone()) + """, cutoff)[0] return {"models": models, "totals": totals, "period_days": days} finally: