1use crate::llm::{Message, TokenUsage, ToolDefinition};
2use crate::planning::Task;
3use crate::prompts::PlanningMode;
4use crate::queue::SessionQueueConfig;
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
13pub enum SessionState {
14 #[default]
15 Unknown = 0,
16 Active = 1,
17 Paused = 2,
18 Completed = 3,
19 Error = 4,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct ContextUsage {
25 pub used_tokens: usize,
26 pub max_tokens: usize,
27 pub percent: f32,
28 pub turns: usize,
29}
30
31impl Default for ContextUsage {
32 fn default() -> Self {
33 Self {
34 used_tokens: 0,
35 max_tokens: 200_000,
36 percent: 0.0,
37 turns: 0,
38 }
39 }
40}
41
42pub const DEFAULT_AUTO_COMPACT_THRESHOLD: f32 = 0.80;
44
45pub(crate) fn default_auto_compact_threshold() -> f32 {
46 DEFAULT_AUTO_COMPACT_THRESHOLD
47}
48
49fn is_false(value: &bool) -> bool {
50 !*value
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct SessionConfig {
56 pub name: String,
57 pub workspace: String,
58 pub system_prompt: Option<String>,
59 pub max_context_length: u32,
60 pub auto_compact: bool,
61 #[serde(default = "default_auto_compact_threshold")]
64 pub auto_compact_threshold: f32,
65 #[serde(default)]
67 pub storage_type: crate::config::StorageBackend,
68 #[serde(skip_serializing_if = "Option::is_none")]
73 pub queue_config: Option<SessionQueueConfig>,
74 #[serde(skip_serializing_if = "Option::is_none")]
76 pub confirmation_policy: Option<crate::hitl::ConfirmationPolicy>,
77 #[serde(skip_serializing_if = "Option::is_none")]
79 pub permission_policy: Option<crate::permissions::PermissionPolicy>,
80 #[serde(default, skip_serializing_if = "is_false")]
82 pub enforce_active_skill_tool_restrictions: bool,
83 #[serde(default, skip_serializing_if = "Option::is_none")]
85 pub max_parallel_tasks: Option<usize>,
86 #[serde(default, skip_serializing_if = "Option::is_none")]
88 pub auto_delegation: Option<crate::config::AutoDelegationConfig>,
89 #[serde(skip_serializing_if = "Option::is_none")]
91 pub parent_id: Option<String>,
92 #[serde(skip_serializing_if = "Option::is_none")]
94 pub security_config: Option<crate::security::SecurityConfig>,
95 #[serde(skip)]
97 pub hook_engine: Option<std::sync::Arc<dyn crate::hooks::HookExecutor>>,
98 #[serde(default)]
100 pub planning_mode: PlanningMode,
101 #[serde(default)]
103 pub goal_tracking: bool,
104 #[serde(default)]
106 pub tool_result_transform_policy: crate::tools::ToolResultTransformPolicyV1,
107}
108
109impl Default for SessionConfig {
110 fn default() -> Self {
111 Self {
112 name: String::new(),
113 workspace: String::new(),
114 system_prompt: None,
115 max_context_length: 0,
116 auto_compact: false,
117 auto_compact_threshold: DEFAULT_AUTO_COMPACT_THRESHOLD,
118 storage_type: crate::config::StorageBackend::default(),
119 queue_config: None,
120 confirmation_policy: None,
121 permission_policy: None,
122 enforce_active_skill_tool_restrictions: false,
123 max_parallel_tasks: None,
124 auto_delegation: None,
125 parent_id: None,
126 security_config: None,
127 hook_engine: None,
128 planning_mode: PlanningMode::default(),
129 goal_tracking: false,
130 tool_result_transform_policy: crate::tools::ToolResultTransformPolicyV1::default(),
131 }
132 }
133}
134
135#[derive(Debug, Clone, Serialize, Deserialize)]
140pub struct SessionData {
141 pub id: String,
143
144 pub config: SessionConfig,
146
147 pub state: SessionState,
149
150 pub messages: Vec<Message>,
152
153 pub context_usage: ContextUsage,
155
156 pub total_usage: TokenUsage,
158
159 #[serde(default)]
161 pub total_cost: f64,
162
163 #[serde(skip_serializing_if = "Option::is_none")]
165 pub model_name: Option<String>,
166
167 #[serde(default)]
169 pub cost_records: Vec<crate::telemetry::LlmCostRecord>,
170
171 pub tool_names: Vec<String>,
173
174 pub thinking_enabled: bool,
176
177 pub thinking_budget: Option<usize>,
179
180 pub created_at: i64,
182
183 pub updated_at: i64,
185
186 #[serde(skip_serializing_if = "Option::is_none")]
188 pub llm_config: Option<LlmConfigData>,
189
190 #[serde(default, alias = "todos")]
192 pub tasks: Vec<Task>,
193
194 #[serde(skip_serializing_if = "Option::is_none")]
196 pub parent_id: Option<String>,
197
198 #[serde(default, skip_serializing_if = "Option::is_none")]
202 pub tenant_id: Option<String>,
203
204 #[serde(default, skip_serializing_if = "Option::is_none")]
208 pub principal: Option<String>,
209
210 #[serde(default, skip_serializing_if = "Option::is_none")]
214 pub agent_template_id: Option<String>,
215
216 #[serde(default, skip_serializing_if = "Option::is_none")]
220 pub correlation_id: Option<String>,
221
222 #[serde(default, skip_serializing_if = "Option::is_none")]
228 pub cognitive_package_binding: Option<crate::cognitive_context::CognitivePackageBindingV1>,
229}
230
231#[derive(Debug, Clone, Serialize, Deserialize)]
233pub struct LlmConfigData {
234 pub provider: String,
235 pub model: String,
236 #[serde(skip_serializing, default)]
238 pub api_key: Option<String>,
239 pub base_url: Option<String>,
240}
241
242impl SessionData {
243 pub fn tool_names_from_definitions(tools: &[ToolDefinition]) -> Vec<String> {
245 tools.iter().map(|t| t.name.clone()).collect()
246 }
247}