1use clap::Subcommand;
4use colored::Colorize;
5use std::time::Duration;
6
7use nika_daemon::{daemon_socket_path, DaemonClient, DaemonRequest, DaemonResponse};
8use nika_engine::error::NikaError;
9
10#[derive(Subcommand)]
11pub enum CacheAction {
12 Stats,
14 Clear,
16}
17
18pub async fn handle_cache_command(action: CacheAction) -> Result<(), NikaError> {
19 let client = DaemonClient::new(daemon_socket_path()).with_timeout(Duration::from_secs(5));
20
21 if !client.socket_exists() {
22 eprintln!(
23 "{} daemon not running — start with: nika daemon start",
24 "✗".red().bold()
25 );
26 return Ok(());
27 }
28
29 match action {
30 CacheAction::Stats => {
31 let resp = client
32 .send(DaemonRequest::CacheStats)
33 .await
34 .map_err(cache_err)?;
35
36 match resp {
37 DaemonResponse::CacheStatsResult {
38 entries,
39 hits,
40 misses,
41 evictions,
42 total_tokens_saved,
43 total_cost_saved,
44 } => {
45 let total = hits + misses;
46 let hit_rate = if total > 0 {
47 (hits as f64 / total as f64) * 100.0
48 } else {
49 0.0
50 };
51
52 println!("{}", "LLM Response Cache".bold());
53 println!(" entries: {}", entries);
54 println!(
55 " hit rate: {:.1}% ({} hits / {} misses)",
56 hit_rate, hits, misses
57 );
58 println!(" evictions: {}", evictions);
59 println!(" tokens saved: {}", total_tokens_saved);
60 println!(" cost saved: ${:.4}", total_cost_saved);
61 }
62 DaemonResponse::Error { code, message } => {
63 eprintln!("{} [{code}] {message}", "✗".red().bold());
64 }
65 _ => eprintln!("{} unexpected response", "✗".red().bold()),
66 }
67 }
68
69 CacheAction::Clear => {
70 let resp = client
71 .send(DaemonRequest::CacheClear)
72 .await
73 .map_err(cache_err)?;
74
75 match resp {
76 DaemonResponse::Ok => {
77 println!("{} cache cleared", "✓".green().bold());
78 }
79 DaemonResponse::Error { code, message } => {
80 eprintln!("{} [{code}] {message}", "✗".red().bold());
81 }
82 _ => eprintln!("{} unexpected response", "✗".red().bold()),
83 }
84 }
85 }
86
87 Ok(())
88}
89
90fn cache_err(e: nika_daemon::DaemonError) -> NikaError {
91 NikaError::Execution(format!("cache: {e}"))
92}