[W9-3a] Enrich agent detail page with sparkline + activity timeline (#529)

Backend: optional agent_slug filter on GET /usage/time-series + UsageService.get_time_series (AgentSpawnSessionTable.agent_slug column already exists — no migration).

Frontend: AgentActivityPanel on the agent detail page — a 7d per-agent token sparkline (recharts AreaChart) + a merged work-session/journal activity timeline. Work-sessions filter by the agent UUID (WorkSessionTable.agent_id is a UUID FK to agents.id), journals by slug. List grid left as-is (avoids 25-agent fan-out). Card last_active deferred (no live hook populates AgentMetrics).

Co-authored-by: Renn F <rennf93@users.noreply.github.com>
This commit is contained in:
Renzo F
2026-07-15 04:33:55 +02:00
committed by GitHub
co-authored by Renn F
parent d9084eeb07
commit 9a364abb74
10 changed files with 352 additions and 11 deletions
+34
View File
@@ -336,6 +336,40 @@ class TestGetTimeSeries:
):
assert field in point, f"Missing field: {field}"
@pytest.mark.asyncio
async def test_agent_slug_filter_scopes_query(self) -> None:
"""agent_slug adds an agent_slug WHERE clause to the time-series query."""
row = _make_row(
bucket=datetime.datetime(2026, 6, 9, 12, 0, 0, tzinfo=datetime.UTC),
tokens_input=100,
tokens_output=100,
tokens_cache_read=_ZERO,
tokens_cache_write=_ZERO,
cost_usd=0.01,
)
svc = _service_with_execute(_result_fetchall([row]))
await svc.get_time_series("7d", agent_slug="be-dev-1")
stmt = svc.session.execute.call_args_list[0][0][0]
sql = str(stmt.compile(compile_kwargs={"literal_binds": True}))
assert "be-dev-1" in sql
@pytest.mark.asyncio
async def test_no_agent_slug_filter_when_none(self) -> None:
"""Without agent_slug the query is not scoped to one agent."""
row = _make_row(
bucket=datetime.datetime(2026, 6, 9, 12, 0, 0, tzinfo=datetime.UTC),
tokens_input=100,
tokens_output=100,
tokens_cache_read=_ZERO,
tokens_cache_write=_ZERO,
cost_usd=0.01,
)
svc = _service_with_execute(_result_fetchall([row]))
await svc.get_time_series("7d")
stmt = svc.session.execute.call_args_list[0][0][0]
sql = str(stmt.compile(compile_kwargs={"literal_binds": True}))
assert "agent_slug" not in sql
# ---------------------------------------------------------------------------
# get_by_agent — pct_of_total sums to 100%