use serde::Deserialize;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
#[derive(Debug, Clone, Default)]
pub struct RateLimitInfo {
#[allow(dead_code)]
pub source: String,
pub five_hour_pct: Option<f64>,
pub five_hour_resets_at: Option<u64>,
pub seven_day_pct: Option<f64>,
pub seven_day_resets_at: Option<u64>,
pub updated_at: Option<u64>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum SessionStatus {
Working,
Waiting,
#[allow(dead_code)]
Error(String),
Done,
}
#[derive(Debug, Clone)]
pub struct ChildProcess {
pub pid: u32,
pub command: String,
pub mem_kb: u64,
pub port: Option<u16>,
}
#[derive(Debug, Clone)]
pub struct OrphanPort {
pub port: u16,
pub pid: u32,
pub command: String,
pub project_name: String,
}
#[derive(Debug, Clone)]
pub struct SubAgent {
pub name: String,
#[allow(dead_code)]
pub agent_type: String,
pub status: String,
pub tokens: u64,
}
#[derive(Debug, Clone)]
pub struct AgentSession {
pub agent_cli: &'static str,
pub pid: u32,
pub session_id: String,
#[allow(dead_code)]
pub cwd: String,
pub project_name: String,
pub started_at: u64,
pub status: SessionStatus,
pub model: String,
pub context_percent: f64,
pub total_input_tokens: u64,
pub total_output_tokens: u64,
pub total_cache_read: u64,
pub total_cache_create: u64,
pub turn_count: u32,
pub current_tasks: Vec<String>,
pub mem_mb: u64,
pub version: String,
pub git_branch: String,
pub git_added: u32,
pub git_modified: u32,
pub token_history: Vec<u64>,
pub subagents: Vec<SubAgent>,
pub mem_file_count: u32,
pub mem_line_count: u32,
pub children: Vec<ChildProcess>,
#[allow(dead_code)]
pub transcript_offset: u64,
pub initial_prompt: String,
}
impl AgentSession {
pub fn total_tokens(&self) -> u64 {
self.total_input_tokens + self.total_output_tokens + self.total_cache_read + self.total_cache_create
}
pub fn active_tokens(&self) -> u64 {
self.total_input_tokens + self.total_output_tokens + self.total_cache_create
}
pub fn elapsed(&self) -> Duration {
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_millis() as u64;
Duration::from_millis(now.saturating_sub(self.started_at))
}
pub fn elapsed_display(&self) -> String {
let secs = self.elapsed().as_secs();
if secs < 60 {
format!("{}s", secs)
} else if secs < 3600 {
format!("{}m", secs / 60)
} else {
format!("{}h {}m", secs / 3600, (secs % 3600) / 60)
}
}
}
#[derive(Debug, Deserialize)]
pub struct SessionFile {
pub pid: u32,
#[serde(rename = "sessionId")]
pub session_id: String,
pub cwd: String,
#[serde(rename = "startedAt")]
pub started_at: u64,
#[serde(default)]
#[allow(dead_code)]
pub kind: String,
}