1use super::Fact;
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7#[serde(rename_all = "snake_case")]
8pub enum RunStatus {
9 Created,
10 Planning,
11 Executing,
12 Verifying,
13 Completed,
14 Failed,
15 Cancelled,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct RunLifecycleEvent {
25 pub run_id: String,
26 pub session_id: String,
27 pub status: RunStatus,
28 #[serde(skip_serializing_if = "Option::is_none")]
29 pub prompt: Option<String>,
30 #[serde(skip_serializing_if = "Option::is_none")]
31 pub result_summary: Option<String>,
32 #[serde(skip_serializing_if = "Option::is_none")]
33 pub error: Option<String>,
34 #[serde(skip_serializing_if = "Option::is_none")]
35 pub started_at: Option<String>,
36 pub updated_at: String,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 pub metadata: Option<HashMap<String, serde_json::Value>>,
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct ArtifactRef {
44 pub id: String,
45 #[serde(skip_serializing_if = "Option::is_none")]
46 pub kind: Option<String>,
47 #[serde(skip_serializing_if = "Option::is_none")]
48 pub uri: Option<String>,
49 #[serde(skip_serializing_if = "Option::is_none")]
50 pub path: Option<String>,
51 #[serde(skip_serializing_if = "Option::is_none")]
52 pub mime_type: Option<String>,
53 #[serde(skip_serializing_if = "Option::is_none")]
54 pub sha256: Option<String>,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 pub size_bytes: Option<u64>,
57 #[serde(skip_serializing_if = "Option::is_none")]
58 pub summary: Option<String>,
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct EvidenceRef {
64 pub kind: String,
65 pub summary: String,
66 #[serde(skip_serializing_if = "Option::is_none")]
67 pub artifact: Option<ArtifactRef>,
68 #[serde(skip_serializing_if = "Option::is_none")]
69 pub metadata: Option<HashMap<String, serde_json::Value>>,
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
74#[serde(rename_all = "snake_case")]
75pub enum TaskStatus {
76 Pending,
77 InProgress,
78 Completed,
79 Failed,
80 Skipped,
81 Cancelled,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct TaskItem {
87 pub id: String,
88 pub title: String,
89 pub status: TaskStatus,
90 #[serde(default, skip_serializing_if = "Vec::is_empty")]
91 pub depends_on: Vec<String>,
92 #[serde(default, skip_serializing_if = "Vec::is_empty")]
93 pub evidence: Vec<EvidenceRef>,
94 #[serde(default, skip_serializing_if = "Vec::is_empty")]
95 pub artifacts: Vec<ArtifactRef>,
96 #[serde(skip_serializing_if = "Option::is_none")]
97 pub error: Option<String>,
98 #[serde(skip_serializing_if = "Option::is_none")]
99 pub updated_at: Option<String>,
100 #[serde(skip_serializing_if = "Option::is_none")]
101 pub metadata: Option<HashMap<String, serde_json::Value>>,
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct TaskListEvent {
107 pub run_id: String,
108 pub session_id: String,
109 pub tasks: Vec<TaskItem>,
110 pub updated_at: String,
111 #[serde(skip_serializing_if = "Option::is_none")]
112 pub metadata: Option<HashMap<String, serde_json::Value>>,
113}
114
115#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
117#[serde(rename_all = "snake_case")]
118pub enum VerificationStatus {
119 Pending,
120 Running,
121 Passed,
122 Failed,
123 Skipped,
124 NeedsReview,
125}
126
127#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct VerificationCheck {
130 pub id: String,
131 pub subject: String,
132 pub status: VerificationStatus,
133 #[serde(skip_serializing_if = "Option::is_none")]
134 pub command: Option<String>,
135 #[serde(skip_serializing_if = "Option::is_none")]
136 pub message: Option<String>,
137 #[serde(default, skip_serializing_if = "Vec::is_empty")]
138 pub evidence: Vec<EvidenceRef>,
139 #[serde(default, skip_serializing_if = "Vec::is_empty")]
140 pub artifacts: Vec<ArtifactRef>,
141 #[serde(skip_serializing_if = "Option::is_none")]
142 pub metadata: Option<HashMap<String, serde_json::Value>>,
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct VerificationEvent {
148 pub run_id: String,
149 pub session_id: String,
150 pub status: VerificationStatus,
151 #[serde(default, skip_serializing_if = "Vec::is_empty")]
152 pub checks: Vec<VerificationCheck>,
153 #[serde(default, skip_serializing_if = "Vec::is_empty")]
154 pub residual_risks: Vec<String>,
155 pub updated_at: String,
156 #[serde(skip_serializing_if = "Option::is_none")]
157 pub metadata: Option<HashMap<String, serde_json::Value>>,
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct MemoryRecallEvent {
163 pub session_id: String,
164 pub query: String,
165 pub memory_type: String,
166 pub max_results: usize,
167 pub working_directory: String,
168}
169
170#[derive(Debug, Clone, Serialize, Deserialize)]
172#[serde(tag = "decision", rename_all = "lowercase")]
173pub enum MemoryRecallDecision {
174 Allow {
176 injected_facts: Vec<Fact>,
177 #[serde(skip_serializing_if = "Option::is_none")]
178 metadata: Option<HashMap<String, serde_json::Value>>,
179 },
180 Block {
182 reason: String,
183 #[serde(skip_serializing_if = "Option::is_none")]
184 metadata: Option<HashMap<String, serde_json::Value>>,
185 },
186}
187
188#[derive(Debug, Clone, Serialize, Deserialize)]
190#[serde(rename_all = "snake_case")]
191pub enum PlanningStrategy {
192 None,
193 StepByStep,
194 TreeOfThoughts,
195 GraphPlanning,
196 Custom(String),
197}
198
199#[derive(Debug, Clone, Serialize, Deserialize)]
201pub struct PlanningEvent {
202 pub session_id: String,
203 pub task_description: String,
204 pub available_strategies: Vec<PlanningStrategy>,
205 #[serde(skip_serializing_if = "Option::is_none")]
206 pub constraints: Option<serde_json::Value>,
207}
208
209#[derive(Debug, Clone, Serialize, Deserialize)]
211#[serde(tag = "decision", rename_all = "lowercase")]
212pub enum PlanningDecision {
213 Allow {
215 selected_strategy: PlanningStrategy,
216 #[serde(skip_serializing_if = "Option::is_none")]
217 planning_template: Option<serde_json::Value>,
218 #[serde(skip_serializing_if = "Option::is_none")]
219 metadata: Option<HashMap<String, serde_json::Value>>,
220 },
221 Block {
223 reason: String,
224 #[serde(skip_serializing_if = "Option::is_none")]
225 metadata: Option<HashMap<String, serde_json::Value>>,
226 },
227 Modify {
229 modified_task: String,
230 #[serde(skip_serializing_if = "Option::is_none")]
231 hints: Option<Vec<String>>,
232 },
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize)]
237#[serde(rename_all = "snake_case")]
238pub enum ReasoningType {
239 ChainOfThought,
240 TreeOfThoughts,
241 ReAct,
242 Reflexion,
243 Other(String),
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize)]
248pub struct ReasoningEvent {
249 pub session_id: String,
250 pub reasoning_type: ReasoningType,
251 pub problem_statement: String,
252 #[serde(skip_serializing_if = "Option::is_none")]
253 pub hints: Option<Vec<String>>,
254}
255
256#[derive(Debug, Clone, Serialize, Deserialize)]
258#[serde(tag = "decision", rename_all = "lowercase")]
259pub enum ReasoningDecision {
260 Allow {
262 #[serde(skip_serializing_if = "Option::is_none")]
263 hints: Option<Vec<String>>,
264 #[serde(skip_serializing_if = "Option::is_none")]
265 metadata: Option<HashMap<String, serde_json::Value>>,
266 },
267 Block {
269 reason: String,
270 #[serde(skip_serializing_if = "Option::is_none")]
271 metadata: Option<HashMap<String, serde_json::Value>>,
272 },
273}
274
275#[derive(Debug, Clone, Serialize, Deserialize)]
277pub struct SuccessEvent {
278 pub session_id: String,
279 pub action_type: String,
280 pub action_summary: String,
281 pub duration_ms: u64,
282}
283
284#[derive(Debug, Clone, Serialize, Deserialize)]
286#[serde(rename_all = "snake_case")]
287pub enum RateLimitType {
288 LlmTokenLimit,
289 LlmRequestLimit,
290 ApiRequestLimit,
291 ToolExecutionLimit,
292 Custom(String),
293}
294
295#[derive(Debug, Clone, Serialize, Deserialize)]
297pub struct RateLimitEvent {
298 pub session_id: String,
299 pub limit_type: RateLimitType,
300 pub retry_after_ms: u64,
301 pub current_usage: String,
302}
303
304#[derive(Debug, Clone, Serialize, Deserialize)]
306#[serde(tag = "decision", rename_all = "lowercase")]
307pub enum RateLimitDecision {
308 Retry {
310 retry_after_ms: u64,
311 #[serde(skip_serializing_if = "Option::is_none")]
312 metadata: Option<HashMap<String, serde_json::Value>>,
313 },
314 Queue,
316 Skip { reason: String },
318}
319
320#[derive(Debug, Clone, Serialize, Deserialize)]
322#[serde(rename_all = "snake_case")]
323pub enum ConfirmationType {
324 SafetyConfirm,
325 UserConfirm,
326 CostConfirm,
327 Custom(String),
328}
329
330#[derive(Debug, Clone, Serialize, Deserialize)]
332pub struct ConfirmationEvent {
333 pub session_id: String,
334 pub confirmation_type: ConfirmationType,
335 pub message: String,
336 #[serde(skip_serializing_if = "Option::is_none")]
337 pub options: Option<Vec<String>>,
338}
339
340#[derive(Debug, Clone, Serialize, Deserialize)]
342#[serde(tag = "decision", rename_all = "lowercase")]
343pub enum ConfirmationDecision {
344 Escalate,
346 Approve,
348 Reject { reason: String },
350}
351
352#[derive(Debug, Clone, Serialize, Deserialize)]
357pub struct IntentDetectionEvent {
358 pub session_id: String,
359 pub prompt: String,
360 pub workspace: String,
361 #[serde(skip_serializing_if = "Option::is_none")]
363 pub language_hint: Option<String>,
364}
365
366#[derive(Debug, Clone, Serialize, Deserialize)]
368pub struct TargetHints {
369 #[serde(skip_serializing_if = "Option::is_none")]
370 pub target_type: Option<String>,
371 #[serde(skip_serializing_if = "Option::is_none")]
372 pub target_name: Option<String>,
373 #[serde(skip_serializing_if = "Option::is_none")]
374 pub domain: Option<String>,
375}
376
377#[derive(Debug, Clone, Serialize, Deserialize)]
379#[serde(tag = "decision", rename_all = "lowercase")]
380pub enum IntentDetectionDecision {
381 Allow {
383 detected_intent: String,
385 confidence: f32,
387 #[serde(skip_serializing_if = "Option::is_none")]
389 target_hints: Option<TargetHints>,
390 },
391 Block { reason: String },
393}