myrmidon / python /src /server /services /stats /domains /agent_metrics.py
tek Atrust
chore(deploy): build monolithic server for Hugging Face
d5ef46f
Raw
History Blame Contribute Delete
5.78 kB
import logging
from datetime import UTC, datetime, timedelta
from typing import Any
logger = logging.getLogger(__name__)
class AgentMetrics:
"""Handles agent execution trends and readiness."""
def __init__(self, supabase_client):
self.supabase = supabase_client
async def get_commander_trends(self) -> list[dict[str, Any]]:
"""Strategic 30-day trend data including full Velocity (GAP-034)."""
thirty_days_ago = (datetime.now(UTC) - timedelta(days=30)).isoformat()
# 1. Token Analytics (Bob/Alice Usage)
marketing_res = self.supabase.table("profiles").select("id").eq("role", "marketing").execute()
m_ids = [r["id"] for r in (marketing_res.data or [])]
token_map: dict[str, int] = {}
if m_ids:
token_res = (
self.supabase.table("token_usage")
.select("created_at, total_tokens")
.in_("user_id", m_ids)
.gt("created_at", thirty_days_ago)
.execute()
)
for row in token_res.data or []:
d = str(row["created_at"][:10])
token_map[d] = token_map.get(d, 0) + int(row["total_tokens"])
# 2. Velocity Aggregation (GAP-034)
velocity_raw: dict[str, list[float]] = {}
def add_velocity(date_str: str, duration_hours: float):
d = date_str[:10]
if d not in velocity_raw:
velocity_raw[d] = []
velocity_raw[d].append(max(0.1, min(168.0, duration_hours)))
# A. Blog Velocity
blog_res = (
self.supabase.table("blog_posts")
.select("created_at, updated_at")
.in_("status", ["published", "changes_requested"])
.gt("updated_at", thirty_days_ago)
.execute()
)
for row in blog_res.data or []:
start = datetime.fromisoformat(row["created_at"].replace("Z", "+00:00"))
end = datetime.fromisoformat(row["updated_at"].replace("Z", "+00:00"))
add_velocity(row["updated_at"], (end - start).total_seconds() / 3600)
# B. Task Velocity (SLA Tracking)
task_res = (
self.supabase.table("archon_tasks")
.select("created_at, completed_at")
.eq("status", "done")
.gt("completed_at", thirty_days_ago)
.execute()
)
for row in task_res.data or []:
start = datetime.fromisoformat(row["created_at"].replace("Z", "+00:00"))
end = datetime.fromisoformat(row["completed_at"].replace("Z", "+00:00"))
add_velocity(row["completed_at"], (end - start).total_seconds() / 3600)
# C. Lead Conversion Velocity
lead_res = (
self.supabase.table("leads")
.select("created_at, updated_at")
.eq("status", "converted")
.gt("updated_at", thirty_days_ago)
.execute()
)
for row in lead_res.data or []:
start = datetime.fromisoformat(row["created_at"].replace("Z", "+00:00"))
end = datetime.fromisoformat(row["updated_at"].replace("Z", "+00:00"))
add_velocity(row["updated_at"], (end - start).total_seconds() / 3600)
all_dates = sorted(set(list(token_map.keys()) + list(velocity_raw.keys())))
return [
{
"date": date[5:],
"bob_tokens": token_map.get(date, 0),
"decision_hours": round(sum(velocity_raw[date]) / len(velocity_raw[date]), 1)
if date in velocity_raw
else 0.0,
}
for date in all_dates
]
async def get_force_readiness(self) -> dict[str, Any]:
"""Combat Power HUD: 90-Day Full Range."""
try:
now = datetime.now(UTC)
ninety_days_ago = (now - timedelta(days=90)).isoformat()
res = (
self.supabase.table("archon_tasks")
.select("id, completed_at, assignee")
.eq("status", "done")
.gt("completed_at", ninety_days_ago)
.execute()
)
all_done_tasks = [t for t in (res.data or []) if t.get("assignee") and t.get("assignee") != "Unassigned"]
total_done = len(all_done_tasks)
baseline_daily = round(total_done / 90, 2)
daily_actual: dict[str, int] = {}
for task in all_done_tasks:
if task.get("completed_at"):
d = task["completed_at"][:10]
daily_actual[d] = daily_actual.get(d, 0) + 1
trend_data = []
for i in range(90, -1, -1):
date_str = (now - timedelta(days=i)).strftime("%Y-%m-%d")
trend_data.append(
{"date": date_str[5:], "actual": daily_actual.get(date_str, 0), "baseline": baseline_daily}
)
ai_names = ["DevBot", "MarketBot", "Librarian", "POBot", "Clockwork"]
ai_done = 0
for t in all_done_tasks:
assignee_str = str(t.get("assignee", ""))
for bot in ai_names:
if bot in assignee_str:
ai_done += 1
break
automation_rate = round((ai_done / total_done) * 100, 1) if total_done > 0 else 0.0
return {
"baseline": baseline_daily,
"trend": trend_data,
"total_done_90d": total_done,
"automation_rate": automation_rate,
"timestamp": now.isoformat(),
}
except Exception as e:
logger.error(f"AgentMetrics: Force readiness failed: {e}")
return {"baseline": 0, "trend": []}