use crate::llm::{Message, TokenUsage, ToolDefinition};
use crate::planning::Task;
use crate::prompts::PlanningMode;
use crate::queue::SessionQueueConfig;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
pub enum SessionState {
#[default]
Unknown = 0,
Active = 1,
Paused = 2,
Completed = 3,
Error = 4,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContextUsage {
pub used_tokens: usize,
pub max_tokens: usize,
pub percent: f32,
pub turns: usize,
}
impl Default for ContextUsage {
fn default() -> Self {
Self {
used_tokens: 0,
max_tokens: 200_000,
percent: 0.0,
turns: 0,
}
}
}
pub const DEFAULT_AUTO_COMPACT_THRESHOLD: f32 = 0.80;
pub(crate) fn default_auto_compact_threshold() -> f32 {
DEFAULT_AUTO_COMPACT_THRESHOLD
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SessionConfig {
pub name: String,
pub workspace: String,
pub system_prompt: Option<String>,
pub max_context_length: u32,
pub auto_compact: bool,
#[serde(default = "default_auto_compact_threshold")]
pub auto_compact_threshold: f32,
#[serde(default)]
pub storage_type: crate::config::StorageBackend,
#[serde(skip_serializing_if = "Option::is_none")]
pub queue_config: Option<SessionQueueConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub confirmation_policy: Option<crate::hitl::ConfirmationPolicy>,
#[serde(skip_serializing_if = "Option::is_none")]
pub permission_policy: Option<crate::permissions::PermissionPolicy>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parent_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub security_config: Option<crate::security::SecurityConfig>,
#[serde(skip)]
pub hook_engine: Option<std::sync::Arc<dyn crate::hooks::HookExecutor>>,
#[serde(default)]
pub planning_mode: PlanningMode,
#[serde(default)]
pub goal_tracking: bool,
}
impl Default for SessionConfig {
fn default() -> Self {
Self {
name: String::new(),
workspace: String::new(),
system_prompt: None,
max_context_length: 0,
auto_compact: false,
auto_compact_threshold: DEFAULT_AUTO_COMPACT_THRESHOLD,
storage_type: crate::config::StorageBackend::default(),
queue_config: None,
confirmation_policy: None,
permission_policy: None,
parent_id: None,
security_config: None,
hook_engine: None,
planning_mode: PlanningMode::default(),
goal_tracking: false,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SessionData {
pub id: String,
pub config: SessionConfig,
pub state: SessionState,
pub messages: Vec<Message>,
pub context_usage: ContextUsage,
pub total_usage: TokenUsage,
#[serde(default)]
pub total_cost: f64,
#[serde(skip_serializing_if = "Option::is_none")]
pub model_name: Option<String>,
#[serde(default)]
pub cost_records: Vec<crate::telemetry::LlmCostRecord>,
pub tool_names: Vec<String>,
pub thinking_enabled: bool,
pub thinking_budget: Option<usize>,
pub created_at: i64,
pub updated_at: i64,
#[serde(skip_serializing_if = "Option::is_none")]
pub llm_config: Option<LlmConfigData>,
#[serde(default, alias = "todos")]
pub tasks: Vec<Task>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parent_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LlmConfigData {
pub provider: String,
pub model: String,
#[serde(skip_serializing, default)]
pub api_key: Option<String>,
pub base_url: Option<String>,
}
impl SessionData {
pub fn tool_names_from_definitions(tools: &[ToolDefinition]) -> Vec<String> {
tools.iter().map(|t| t.name.clone()).collect()
}
}