| 2287 | } |
| 2288 | |
| 2289 | async fn handle_stats_command( |
| 2290 | days: Option<i64>, |
| 2291 | tools_limit: Option<usize>, |
| 2292 | models_limit: Option<usize>, |
| 2293 | project: Option<String>, |
| 2294 | ) -> anyhow::Result<()> { |
| 2295 | let db = Database::new().await?; |
| 2296 | let session_repo = SessionRepository::new(db.pool().clone()); |
| 2297 | let message_repo = MessageRepository::new(db.pool().clone()); |
| 2298 | |
| 2299 | let mut sessions = session_repo.list(None, 50_000).await?; |
| 2300 | if let Some(project) = project { |
| 2301 | if project.is_empty() { |
| 2302 | let cwd = std::env::current_dir()?.display().to_string(); |
| 2303 | sessions.retain(|s| s.directory == cwd); |
| 2304 | } else { |
| 2305 | sessions.retain(|s| s.project_id == project); |
| 2306 | } |
| 2307 | } |
| 2308 | |
| 2309 | if let Some(days) = days { |
| 2310 | let now = chrono::Utc::now().timestamp_millis(); |
| 2311 | let cutoff = if days == 0 { |
| 2312 | let dt = chrono::Utc::now() |
| 2313 | .date_naive() |
| 2314 | .and_hms_opt(0, 0, 0) |
| 2315 | .unwrap(); |
| 2316 | chrono::DateTime::<chrono::Utc>::from_naive_utc_and_offset(dt, chrono::Utc) |
| 2317 | .timestamp_millis() |
| 2318 | } else { |
| 2319 | now - (days * 24 * 60 * 60 * 1000) |
| 2320 | }; |
| 2321 | sessions.retain(|s| s.time.updated >= cutoff); |
| 2322 | } |
| 2323 | |
| 2324 | let mut total_messages = 0usize; |
| 2325 | let mut total_cost = 0.0f64; |
| 2326 | let mut total_input = 0u64; |
| 2327 | let mut total_output = 0u64; |
| 2328 | let mut total_reasoning = 0u64; |
| 2329 | let mut total_cache_read = 0u64; |
| 2330 | let mut total_cache_write = 0u64; |
| 2331 | let mut tool_usage: BTreeMap<String, usize> = BTreeMap::new(); |
| 2332 | let mut model_usage: BTreeMap<String, usize> = BTreeMap::new(); |
| 2333 | |
| 2334 | for session in &sessions { |
| 2335 | if let Some(usage) = &session.usage { |
| 2336 | total_cost += usage.total_cost; |
| 2337 | total_input += usage.input_tokens; |
| 2338 | total_output += usage.output_tokens; |
| 2339 | total_reasoning += usage.reasoning_tokens; |
| 2340 | total_cache_read += usage.cache_read_tokens; |
| 2341 | total_cache_write += usage.cache_write_tokens; |
| 2342 | } |
| 2343 | |
| 2344 | let messages = message_repo.list_for_session(&session.id).await?; |
| 2345 | total_messages += messages.len(); |
| 2346 | |