- Replay models: StepType enum, ReplayStep, ReplayPage frozen dataclasses
- Checkpoint transformer: PostgresSaver JSONB -> structured timeline steps
- Replay API: GET /api/conversations (paginated), GET /api/replay/{thread_id}
- Analytics models: AgentUsage, InterruptStats, AnalyticsResult
- Analytics event recorder: Protocol + PostgresAnalyticsRecorder + NoOp
- Analytics queries: resolution_rate, agent_usage, escalation_rate, cost, interrupts
- Analytics API: GET /api/analytics?range=Xd with envelope response
- DB migration: analytics_events table + conversations column additions
- 74 new tests, 399 total passing, 92.87% coverage
39 lines
830 B
Python
39 lines
830 B
Python
"""Value objects for analytics dashboard."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class AgentUsage:
|
|
"""Agent usage statistics within a time range."""
|
|
|
|
agent: str
|
|
count: int
|
|
percentage: float
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class InterruptStats:
|
|
"""Interrupt approval/rejection statistics within a time range."""
|
|
|
|
total: int = 0
|
|
approved: int = 0
|
|
rejected: int = 0
|
|
expired: int = 0
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class AnalyticsResult:
|
|
"""Full analytics result for a given time range."""
|
|
|
|
range: str
|
|
total_conversations: int
|
|
resolution_rate: float
|
|
escalation_rate: float
|
|
avg_turns_per_conversation: float
|
|
avg_cost_per_conversation_usd: float
|
|
agent_usage: tuple[AgentUsage, ...]
|
|
interrupt_stats: InterruptStats
|