use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SessionStatus {
Idle,
Working,
WaitingApproval,
Error,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum SessionMode {
Interactive,
#[serde(alias = "auto-allow")]
Guarded,
Autonomous,
}
impl Default for SessionMode {
fn default() -> Self {
Self::Interactive
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SessionInfo {
pub id: String,
pub name: String,
pub workdir: String,
pub status: SessionStatus,
pub created_by: String,
pub created_at: String,
pub attached_clients: u32,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub mode: Option<SessionMode>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub turns_remaining: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub pinned_files: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub agent_uri: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub subagents: Option<Vec<Subagent>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub usage: Option<SessionUsage>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rotation: Option<RotationInfo>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub queued_messages: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub fallback_model: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub provider_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub forked_from: Option<ForkedFrom>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub worktree: Option<SessionWorktree>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ForkedFrom {
pub session_id: String,
pub name: String,
pub at_turn: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SessionWorktree {
pub path: String,
pub branch: String,
pub created_by_codeoid: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RotationInfo {
pub count: u32,
pub last_rotated_at: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub claude_code_session_id: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SessionUsage {
pub input_tokens: u64,
pub output_tokens: u64,
pub cache_read_tokens: u64,
pub cache_creation_tokens: u64,
pub total_cost_usd: f64,
pub num_turns: u32,
pub duration_ms: u64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub recent_turns: Option<Vec<TurnUsage>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub peak_input_tokens: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub last_turn_input_tokens: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub last_turn_output_tokens: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub last_turn_cost_usd: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub last_turn_cache_hit_rate: Option<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TurnUsage {
pub turn_number: u32,
pub created_at: i64,
pub input_tokens: u64,
pub output_tokens: u64,
pub cache_read_tokens: u64,
pub cache_creation_tokens: u64,
pub total_cost_usd: f64,
pub duration_ms: u64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub stop_reason: Option<String>,
pub total_input_tokens: u64,
pub billable_input_tokens: u64,
pub cache_hit_rate: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Subagent {
pub agent_id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub wimse_uri: Option<String>,
pub agent_type: String,
pub spawned_at: i64,
pub active: bool,
}