1pub mod heatmap;
2pub mod overview;
3pub mod project;
4pub mod session;
5pub mod trend;
6pub mod validate;
7pub mod wrapped;
8
9use crate::data::models::{AttributionData, GlobalDataQuality, PrLinkInfo, TokenUsage};
10use chrono::{DateTime, NaiveDate, Utc};
11use serde::Serialize;
12use std::collections::HashMap;
13
14#[derive(Debug, Default, Clone, Serialize)]
17pub struct AggregatedTokens {
18 pub input_tokens: u64,
19 pub output_tokens: u64,
20 pub cache_creation_tokens: u64, pub cache_write_5m_tokens: u64, pub cache_write_1h_tokens: u64, pub cache_read_tokens: u64,
24 pub turns: usize,
25}
26
27impl AggregatedTokens {
28 pub fn add_usage(&mut self, usage: &TokenUsage) {
29 self.input_tokens += usage.input_tokens.unwrap_or(0);
30 self.output_tokens += usage.output_tokens.unwrap_or(0);
31 self.cache_creation_tokens += usage.cache_creation_input_tokens.unwrap_or(0);
32 self.cache_read_tokens += usage.cache_read_input_tokens.unwrap_or(0);
33
34 if let Some(ref detail) = usage.cache_creation {
36 self.cache_write_5m_tokens += detail.ephemeral_5m_input_tokens.unwrap_or(0);
37 self.cache_write_1h_tokens += detail.ephemeral_1h_input_tokens.unwrap_or(0);
38 }
39
40 self.turns += 1;
41 }
42
43 pub fn context_tokens(&self) -> u64 {
44 self.input_tokens + self.cache_creation_tokens + self.cache_read_tokens
45 }
46}
47
48#[derive(Debug, Clone, Default, Serialize)]
51pub struct TurnCostBreakdown {
52 pub input_cost: f64,
53 pub output_cost: f64,
54 pub cache_write_5m_cost: f64,
55 pub cache_write_1h_cost: f64,
56 pub cache_read_cost: f64,
57 pub total: f64,
58}
59
60#[derive(Debug, Default, Serialize)]
61pub struct CostByCategory {
62 pub input_cost: f64,
63 pub output_cost: f64,
64 pub cache_write_5m_cost: f64,
65 pub cache_write_1h_cost: f64,
66 pub cache_read_cost: f64,
67}
68
69pub struct OverviewResult {
72 pub total_sessions: usize,
73 pub total_turns: usize,
74 pub total_agent_turns: usize,
75 pub tokens_by_model: HashMap<String, AggregatedTokens>,
76 pub cost_by_model: HashMap<String, f64>,
77 pub total_cost: f64,
78 pub hourly_distribution: [usize; 24],
79 pub quality: GlobalDataQuality,
80 pub subscription_value: Option<SubscriptionValue>,
81 pub weekday_hour_matrix: [[usize; 24]; 7], pub tool_counts: Vec<(String, usize)>, pub cost_by_category: CostByCategory, pub session_summaries: Vec<SessionSummary>, pub total_output_tokens: u64,
87 pub total_context_tokens: u64,
88 pub avg_cache_hit_rate: f64,
89 pub cache_savings: CacheSavings,
90 pub output_ratio: f64, pub cost_per_turn: f64, pub tokens_per_output_turn: u64, }
95
96#[derive(Debug, Default, Serialize)]
98pub struct CacheSavings {
99 pub total_saved: f64, pub without_cache_cost: f64, pub with_cache_cost: f64, pub savings_pct: f64, pub by_model: Vec<(String, f64)>, }
105
106#[derive(Debug, Serialize)]
107pub struct SubscriptionValue {
108 pub monthly_price: f64,
109 pub api_equivalent: f64,
110 pub value_multiplier: f64,
111}
112
113#[derive(Debug, Serialize)]
116pub struct ProjectResult {
117 pub projects: Vec<ProjectSummary>,
118}
119
120#[derive(Debug, Serialize)]
121pub struct ProjectSummary {
122 pub name: String,
123 pub display_name: String,
124 pub session_count: usize,
125 pub total_turns: usize,
126 pub agent_turns: usize,
127 pub tokens: AggregatedTokens,
128 pub cost: f64,
129 pub primary_model: String,
130}
131
132#[derive(Debug, Serialize)]
135pub struct SessionResult {
136 pub session_id: String,
137 pub project: String,
138 pub turn_details: Vec<TurnDetail>,
139 pub agent_summary: AgentSummary,
140 pub total_tokens: AggregatedTokens,
141 pub total_cost: f64,
142 pub stop_reason_counts: HashMap<String, usize>,
143 pub duration_minutes: f64,
145 pub max_context: u64,
146 pub compaction_count: usize,
147 pub cache_write_5m_pct: f64, pub cache_write_1h_pct: f64, pub model: String, pub title: Option<String>,
152 pub tags: Vec<String>,
153 pub mode: Option<String>,
154 pub pr_links: Vec<PrLinkInfo>,
155 pub user_prompt_count: usize,
157 pub autonomy_ratio: f64, pub api_error_count: usize,
160 pub tool_error_count: usize,
161 pub truncated_count: usize, pub speculation_accepts: usize,
164 pub speculation_time_saved_ms: f64,
165 pub service_tiers: HashMap<String, usize>,
167 pub speeds: HashMap<String, usize>,
168 pub inference_geos: HashMap<String, usize>,
169 pub git_branches: HashMap<String, usize>,
171 pub collapse_count: usize,
173 pub collapse_summaries: Vec<String>,
174 pub collapse_avg_risk: f64,
175 pub collapse_max_risk: f64,
176 pub attribution: Option<AttributionData>,
178}
179
180#[derive(Debug, Serialize)]
181pub struct TurnDetail {
182 pub turn_number: usize,
183 pub timestamp: DateTime<Utc>,
184 pub model: String,
185 pub input_tokens: u64,
186 pub output_tokens: u64,
187 pub cache_write_5m_tokens: u64, pub cache_write_1h_tokens: u64, pub cache_read_tokens: u64,
190 pub context_size: u64,
191 pub cache_hit_rate: f64,
192 pub cost: f64,
193 pub cost_breakdown: TurnCostBreakdown, pub stop_reason: Option<String>,
195 pub is_agent: bool,
196 pub is_compaction: bool, pub context_delta: i64, pub user_text: Option<String>, pub assistant_text: Option<String>, pub tool_names: Vec<String>, }
202
203#[derive(Debug, Default, Serialize)]
204pub struct AgentSummary {
205 pub total_agent_turns: usize,
206 pub agent_output_tokens: u64,
207 pub agent_cost: f64,
208 pub agents: Vec<AgentDetail>,
209}
210
211#[derive(Debug, Serialize)]
212pub struct AgentDetail {
213 pub agent_id: String,
214 pub agent_type: String,
215 pub description: String,
216 pub turns: usize,
217 pub output_tokens: u64,
218 pub cost: f64,
219}
220
221#[derive(Debug, Serialize)]
225pub struct SessionSummary {
226 pub session_id: String,
227 pub project_display_name: String,
228 pub first_timestamp: Option<DateTime<Utc>>,
229 pub duration_minutes: f64,
230 pub model: String, pub turn_count: usize,
232 pub agent_turn_count: usize,
233 pub output_tokens: u64,
234 pub context_tokens: u64,
235 pub max_context: u64,
236 pub cache_hit_rate: f64, pub cache_write_5m_pct: f64, pub compaction_count: usize,
239 pub cost: f64,
240 pub tool_use_count: usize, pub top_tools: Vec<(String, usize)>, pub turn_details: Option<Vec<TurnDetail>>, pub output_ratio: f64, pub cost_per_turn: f64, }
247
248#[derive(Debug, Serialize)]
251pub struct TrendResult {
252 pub entries: Vec<TrendEntry>,
253 pub group_label: String, }
255
256#[derive(Debug, Serialize)]
257pub struct TrendEntry {
258 pub label: String, pub date: NaiveDate,
260 pub session_count: usize,
261 pub turn_count: usize,
262 pub tokens: AggregatedTokens,
263 pub cost: f64,
264 pub models: HashMap<String, u64>,
265 pub cost_by_category: CostByCategory,
267}
268
269pub type DailyStats = TrendEntry;