pub mod overview;
pub mod project;
pub mod session;
pub mod trend;
pub mod validate;
use crate::data::models::{GlobalDataQuality, TokenUsage};
use chrono::{DateTime, NaiveDate, Utc};
use std::collections::HashMap;
#[derive(Debug, Default, Clone)]
pub struct AggregatedTokens {
pub input_tokens: u64,
pub output_tokens: u64,
pub cache_creation_tokens: u64, pub cache_write_5m_tokens: u64, pub cache_write_1h_tokens: u64, pub cache_read_tokens: u64,
pub turns: usize,
}
impl AggregatedTokens {
pub fn add_usage(&mut self, usage: &TokenUsage) {
self.input_tokens += usage.input_tokens.unwrap_or(0);
self.output_tokens += usage.output_tokens.unwrap_or(0);
self.cache_creation_tokens += usage.cache_creation_input_tokens.unwrap_or(0);
self.cache_read_tokens += usage.cache_read_input_tokens.unwrap_or(0);
if let Some(ref detail) = usage.cache_creation {
self.cache_write_5m_tokens += detail.ephemeral_5m_input_tokens.unwrap_or(0);
self.cache_write_1h_tokens += detail.ephemeral_1h_input_tokens.unwrap_or(0);
}
self.turns += 1;
}
pub fn context_tokens(&self) -> u64 {
self.input_tokens + self.cache_creation_tokens + self.cache_read_tokens
}
}
#[derive(Debug, Clone, Default)]
pub struct TurnCostBreakdown {
pub input_cost: f64,
pub output_cost: f64,
pub cache_write_5m_cost: f64,
pub cache_write_1h_cost: f64,
pub cache_read_cost: f64,
pub total: f64,
}
#[derive(Debug, Default)]
pub struct CostByCategory {
pub input_cost: f64,
pub output_cost: f64,
pub cache_write_5m_cost: f64,
pub cache_write_1h_cost: f64,
pub cache_read_cost: f64,
}
pub struct OverviewResult {
pub total_sessions: usize,
pub total_turns: usize,
pub total_agent_turns: usize,
pub tokens_by_model: HashMap<String, AggregatedTokens>,
pub cost_by_model: HashMap<String, f64>,
pub total_cost: f64,
pub hourly_distribution: [usize; 24],
pub quality: GlobalDataQuality,
pub subscription_value: Option<SubscriptionValue>,
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,
pub total_context_tokens: u64,
pub avg_cache_hit_rate: f64,
pub cache_savings: CacheSavings,
}
#[derive(Debug, Default)]
pub struct CacheSavings {
pub total_saved: f64, pub without_cache_cost: f64, pub with_cache_cost: f64, pub savings_pct: f64, pub by_model: Vec<(String, f64)>, }
pub struct SubscriptionValue {
pub monthly_price: f64,
pub api_equivalent: f64,
pub value_multiplier: f64,
}
pub struct ProjectResult {
pub projects: Vec<ProjectSummary>,
}
pub struct ProjectSummary {
pub name: String,
pub display_name: String,
pub session_count: usize,
pub total_turns: usize,
pub agent_turns: usize,
pub tokens: AggregatedTokens,
pub cost: f64,
pub primary_model: String,
}
pub struct SessionResult {
pub session_id: String,
pub project: String,
pub turn_details: Vec<TurnDetail>,
pub agent_summary: AgentSummary,
pub total_tokens: AggregatedTokens,
pub total_cost: f64,
pub stop_reason_counts: HashMap<String, usize>,
pub duration_minutes: f64,
pub max_context: u64,
pub compaction_count: usize,
pub cache_write_5m_pct: f64, pub cache_write_1h_pct: f64, pub model: String, }
#[derive(Debug)]
pub struct TurnDetail {
pub turn_number: usize,
pub timestamp: DateTime<Utc>,
pub model: String,
pub input_tokens: u64,
pub output_tokens: u64,
pub cache_write_5m_tokens: u64, pub cache_write_1h_tokens: u64, pub cache_read_tokens: u64,
pub context_size: u64,
pub cache_hit_rate: f64,
pub cost: f64,
pub cost_breakdown: TurnCostBreakdown, pub stop_reason: Option<String>,
pub is_agent: bool,
pub is_compaction: bool, pub context_delta: i64, pub user_text: Option<String>, pub assistant_text: Option<String>, pub tool_names: Vec<String>, }
#[derive(Debug, Default)]
pub struct AgentSummary {
pub total_agent_turns: usize,
pub agent_output_tokens: u64,
pub agent_cost: f64,
pub agents: Vec<AgentDetail>,
}
#[derive(Debug)]
pub struct AgentDetail {
pub agent_id: String,
pub agent_type: String,
pub description: String,
pub turns: usize,
pub output_tokens: u64,
pub cost: f64,
}
#[derive(Debug)]
pub struct SessionSummary {
pub session_id: String,
pub project_display_name: String,
pub first_timestamp: Option<DateTime<Utc>>,
pub duration_minutes: f64,
pub model: String, pub turn_count: usize,
pub agent_turn_count: usize,
pub output_tokens: u64,
pub context_tokens: u64,
pub max_context: u64,
pub cache_hit_rate: f64, pub cache_write_5m_pct: f64, pub compaction_count: usize,
pub cost: f64,
pub tool_use_count: usize, pub top_tools: Vec<(String, usize)>, pub turn_details: Option<Vec<TurnDetail>>, }
pub struct TrendResult {
pub entries: Vec<TrendEntry>,
pub group_label: String, }
pub struct TrendEntry {
pub label: String, pub date: NaiveDate,
pub session_count: usize,
pub turn_count: usize,
pub tokens: AggregatedTokens,
pub cost: f64,
pub models: HashMap<String, u64>,
pub cost_by_category: CostByCategory,
}
pub type DailyStats = TrendEntry;