1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4
5use crate::message::Message;
6use crate::model::{ModelResponse, Usage};
7
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10pub struct Event {
11 pub run_id: String,
12 pub seq: u64,
14 pub at: DateTime<Utc>,
15 pub kind: EventKind,
16}
17
18#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
19#[serde(tag = "type", rename_all = "snake_case")]
20pub enum EventKind {
21 RunStarted {
22 agent: String,
23 input: Message,
24 },
25 ModelCalled {
26 step: u32,
27 response: ModelResponse,
28 cost_usd: Option<f64>,
29 duration_ms: u64,
30 },
31 ModelFailed {
34 step: u32,
35 error: String,
36 #[serde(default)]
38 usage: Usage,
39 #[serde(default)]
40 cost_usd: Option<f64>,
41 },
42 ToolDenied {
43 call_id: String,
44 tool: String,
45 reason: String,
46 },
47 ApprovalRequested {
48 call_id: String,
49 tool: String,
50 input: Value,
51 reason: String,
52 },
53 ApprovalDecided {
54 call_id: String,
55 approved: bool,
56 by: Option<String>,
57 note: Option<String>,
58 },
59 ToolCompleted {
60 call_id: String,
61 tool: String,
62 output: Value,
63 is_error: bool,
64 duration_ms: u64,
65 },
66 BudgetExceeded {
67 reason: String,
68 },
69 RunCompleted {
70 output: String,
71 #[serde(default, skip_serializing_if = "Option::is_none")]
73 structured: Option<Value>,
74 },
75 FinishRejected {
77 step: u32,
78 reason: String,
79 },
80 RunFailed {
81 error: String,
82 },
83}
84
85impl EventKind {
86 pub fn name(&self) -> &'static str {
87 match self {
88 EventKind::RunStarted { .. } => "run_started",
89 EventKind::ModelCalled { .. } => "model_called",
90 EventKind::ModelFailed { .. } => "model_failed",
91 EventKind::ToolDenied { .. } => "tool_denied",
92 EventKind::ApprovalRequested { .. } => "approval_requested",
93 EventKind::ApprovalDecided { .. } => "approval_decided",
94 EventKind::ToolCompleted { .. } => "tool_completed",
95 EventKind::BudgetExceeded { .. } => "budget_exceeded",
96 EventKind::RunCompleted { .. } => "run_completed",
97 EventKind::FinishRejected { .. } => "finish_rejected",
98 EventKind::RunFailed { .. } => "run_failed",
99 }
100 }
101}