1use serde::{Deserialize, Serialize};
2
3
4use crate::types::message::{Message, ToolCall, ToolResult};
5
6#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
15pub struct ProviderReplay {
16 #[serde(default, skip_serializing_if = "Option::is_none")]
17 pub native_blocks: Option<Vec<serde_json::Value>>,
18 #[serde(default, skip_serializing_if = "Option::is_none")]
19 pub reasoning_content: Option<String>,
20 #[serde(flatten, default, skip_serializing_if = "serde_json::Map::is_empty")]
21 pub extra: serde_json::Map<String, serde_json::Value>,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
25#[serde(tag = "kind", rename_all = "snake_case")]
26pub enum RollbackReason {
27 FatalToolError { tool_name: String, error: String },
28 GovernanceDenied { tool_name: String, reason: String },
29 ProviderFailure { error: String },
30 Timeout,
31 UserInterrupt,
32 MalformedReplay { reason: String },
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
40#[serde(tag = "kind", rename_all = "snake_case")]
41pub enum SessionEvent {
42 RunStarted {
44 run_id: String,
45 goal: String,
46 #[serde(default)]
47 criteria: Vec<String>,
48 agent_id: Option<String>,
49 system_prompt: Option<String>,
50 },
51 LlmCompleted {
52 turn: u32,
53 message: Message,
54 #[serde(default, skip_serializing_if = "Option::is_none")]
55 provider_replay: Option<ProviderReplay>,
56 },
57 ToolRequested {
58 turn: u32,
59 calls: Vec<ToolCall>,
60 },
61 ToolCompleted {
62 turn: u32,
63 results: Vec<ToolResult>,
64 },
65 Compressed {
66 turn: u32,
67 archived_seq_range: (u64, u64),
68 #[serde(default, skip_serializing_if = "Option::is_none")]
69 action: Option<String>,
70 #[serde(default, skip_serializing_if = "Option::is_none")]
71 summary: Option<String>,
72 #[serde(default, skip_serializing_if = "Option::is_none")]
73 summary_tokens: Option<u32>,
74 #[serde(default, skip_serializing_if = "Option::is_none")]
75 archive_ref: Option<String>,
76 #[serde(default, skip_serializing_if = "Vec::is_empty")]
77 preserved_refs: Vec<String>,
78 },
79 PageOut {
81 turn: u32,
82 #[serde(default, skip_serializing_if = "Option::is_none")]
83 action: Option<String>,
84 #[serde(default, skip_serializing_if = "Option::is_none")]
85 summary: Option<String>,
86 #[serde(default, skip_serializing_if = "Option::is_none")]
87 tier_hint: Option<String>,
88 #[serde(default)]
89 message_count: u32,
90 },
91 PageIn {
93 turn: u32,
94 entry_count: u32,
95 },
96 LargeResultSpooled {
98 turn: u32,
99 call_id: String,
100 tool: String,
101 original_size: u32,
102 preview_size: u32,
103 #[serde(default, skip_serializing_if = "Option::is_none")]
104 spool_ref: Option<String>,
105 },
106 RunTerminal {
107 reason: String,
108 turns_used: u32,
109 total_tokens: u64,
110 },
111
112 ToolArgumentRepaired {
115 turn: u32,
116 tool: String,
117 original_arguments: String,
118 repaired_arguments: String,
119 },
120 PermissionRequested {
122 turn: u32,
123 tool: String,
124 arguments: String,
125 reason: Option<String>,
126 },
127 PermissionResolved {
129 turn: u32,
130 approved: bool,
131 responder: String, },
133 ToolDenied {
135 turn: u32,
136 call_id: String,
137 tool_name: String,
138 reason: String,
139 },
140
141 CapabilityChanged {
144 turn: u32,
145 #[serde(default, skip_serializing_if = "Vec::is_empty")]
146 added: Vec<String>,
147 #[serde(default, skip_serializing_if = "Vec::is_empty")]
148 removed: Vec<String>,
149 #[serde(default, skip_serializing_if = "Option::is_none")]
150 change_kind: Option<String>,
151 #[serde(default, skip_serializing_if = "Option::is_none")]
152 capability_id: Option<String>,
153 #[serde(default, skip_serializing_if = "Option::is_none")]
154 version: Option<String>,
155 #[serde(default, skip_serializing_if = "Option::is_none")]
156 mounted_by: Option<String>,
157 #[serde(default, skip_serializing_if = "Option::is_none")]
158 mount_reason: Option<String>,
159 },
160 ContextRenewed {
162 turn: u32,
163 sprint: u32,
164 handoff_ref: String,
165 },
166
167 Suspended {
169 turn: u32,
170 reason: String,
171 #[serde(default, skip_serializing_if = "Vec::is_empty")]
172 pending_calls: Vec<String>,
173 },
174 Resumed {
176 turn: u32,
177 #[serde(default, skip_serializing_if = "Vec::is_empty")]
178 approved: Vec<String>,
179 #[serde(default, skip_serializing_if = "Vec::is_empty")]
180 denied: Vec<String>,
181 },
182 ToolGated {
184 turn: u32,
185 call_id: String,
186 tool: String,
187 reason: String,
188 },
189 SignalDisposed {
191 turn: u32,
192 signal_id: String,
193 disposition: String,
194 queue_depth: u32,
195 },
196 BudgetExceeded {
198 turn: u32,
199 budget: String,
200 },
201 CheckpointTaken {
203 turn: u32,
204 history_len: u32,
205 },
206 Rollbacked {
208 turn: u32,
209 checkpoint_history_len: u32,
210 #[serde(default, skip_serializing_if = "Option::is_none")]
211 reason: Option<RollbackReason>,
212 },
213
214 AgentProcessChanged {
217 turn: u32,
218 agent_id: String,
219 parent_session_id: String,
220 role: String,
221 isolation: String,
222 context_inheritance: String,
223 state: String,
224 #[serde(default, skip_serializing_if = "Vec::is_empty")]
225 permitted_capability_ids: Vec<String>,
226 #[serde(default, skip_serializing_if = "Option::is_none")]
227 result_termination: Option<String>,
228 },
229
230 MilestoneAdvanced {
233 turn: u32,
234 phase_id: String,
235 #[serde(default)]
236 capabilities_unlocked: Vec<String>,
237 },
238 MilestoneBlocked {
240 turn: u32,
241 phase_id: String,
242 reason: String,
243 },
244
245 MemoryWritten {
248 turn: u32,
249 memory_id: String,
250 memory_kind: String,
251 size_bytes: u32,
252 },
253 MemoryQueried {
255 turn: u32,
256 query_context: String,
257 requested_k: usize,
258 requires_async_response: bool,
259 },
260 MemoryValidationFailed {
262 turn: u32,
263 memory_id: String,
264 error: String,
265 },
266 MemoryRetrievalResult {
268 retrieval: crate::mm::memory::MemoryRetrieval,
269 },
270}
271
272impl SessionEvent {
273 pub fn kind_str(&self) -> &'static str {
275 match self {
276 Self::RunStarted { .. } => "run_started",
277 Self::LlmCompleted { .. } => "llm_completed",
278 Self::ToolRequested { .. } => "tool_requested",
279 Self::ToolCompleted { .. } => "tool_completed",
280 Self::Compressed { .. } => "compressed",
281 Self::PageOut { .. } => "page_out",
282 Self::PageIn { .. } => "page_in",
283 Self::LargeResultSpooled { .. } => "large_result_spooled",
284 Self::RunTerminal { .. } => "run_terminal",
285 Self::ToolArgumentRepaired { .. } => "tool_argument_repaired",
286 Self::PermissionRequested { .. } => "permission_requested",
287 Self::PermissionResolved { .. } => "permission_resolved",
288 Self::ToolDenied { .. } => "tool_denied",
289 Self::CapabilityChanged { .. } => "capability_changed",
290 Self::ContextRenewed { .. } => "context_renewed",
291 Self::Suspended { .. } => "suspended",
292 Self::Resumed { .. } => "resumed",
293 Self::ToolGated { .. } => "tool_gated",
294 Self::SignalDisposed { .. } => "signal_disposed",
295 Self::BudgetExceeded { .. } => "budget_exceeded",
296 Self::CheckpointTaken { .. } => "checkpoint_taken",
297 Self::Rollbacked { .. } => "rollbacked",
298 Self::AgentProcessChanged { .. } => "agent_process_changed",
299 Self::MilestoneAdvanced { .. } => "milestone_advanced",
300 Self::MilestoneBlocked { .. } => "milestone_blocked",
301 Self::MemoryWritten { .. } => "memory_written",
302 Self::MemoryQueried { .. } => "memory_queried",
303 Self::MemoryValidationFailed { .. } => "memory_validation_failed",
304 Self::MemoryRetrievalResult { .. } => "memory_retrieval_result",
305 }
306 }
307
308 pub fn is_kernel_os_event(&self) -> bool {
310 matches!(
311 self,
312 Self::Compressed { .. }
313 | Self::PageOut { .. }
314 | Self::PageIn { .. }
315 | Self::LargeResultSpooled { .. }
316 | Self::CapabilityChanged { .. }
317 | Self::ContextRenewed { .. }
318 | Self::Suspended { .. }
319 | Self::Resumed { .. }
320 | Self::ToolGated { .. }
321 | Self::SignalDisposed { .. }
322 | Self::BudgetExceeded { .. }
323 | Self::CheckpointTaken { .. }
324 | Self::Rollbacked { .. }
325 | Self::AgentProcessChanged { .. }
326 | Self::MilestoneAdvanced { .. }
327 | Self::MilestoneBlocked { .. }
328 | Self::MemoryWritten { .. }
329 | Self::MemoryQueried { .. }
330 | Self::MemoryValidationFailed { .. }
331 )
332 }
333}