1use crate::types::{ThreadId, TokenUsage, ToolResult, ToolTier};
16use serde::{Deserialize, Serialize};
17use std::time::Duration;
18
19#[derive(Clone, Debug, Serialize, Deserialize)]
22#[serde(tag = "type", rename_all = "snake_case")]
23pub enum AgentEvent {
24 Start { thread_id: ThreadId, turn: usize },
26
27 Thinking { text: String },
29
30 TextDelta { delta: String },
32
33 Text { text: String },
35
36 ToolCallStart {
38 id: String,
39 name: String,
40 input: serde_json::Value,
41 tier: ToolTier,
42 },
43
44 ToolCallEnd {
46 id: String,
47 name: String,
48 result: ToolResult,
49 },
50
51 ToolRequiresConfirmation {
53 id: String,
54 name: String,
55 input: serde_json::Value,
56 description: String,
57 },
58
59 ToolRequiresPin {
61 id: String,
62 name: String,
63 input: serde_json::Value,
64 description: String,
65 },
66
67 TurnComplete { turn: usize, usage: TokenUsage },
69
70 Done {
72 thread_id: ThreadId,
73 total_turns: usize,
74 total_usage: TokenUsage,
75 duration: Duration,
76 },
77
78 Error { message: String, recoverable: bool },
80
81 ContextCompacted {
83 original_count: usize,
85 new_count: usize,
87 original_tokens: usize,
89 new_tokens: usize,
91 },
92
93 SubagentProgress {
95 subagent_id: String,
97 subagent_name: String,
99 tool_name: String,
101 tool_context: String,
103 completed: bool,
105 success: bool,
107 tool_count: u32,
109 total_tokens: u64,
111 },
112}
113
114impl AgentEvent {
115 #[must_use]
116 pub const fn start(thread_id: ThreadId, turn: usize) -> Self {
117 Self::Start { thread_id, turn }
118 }
119
120 #[must_use]
121 pub fn thinking(text: impl Into<String>) -> Self {
122 Self::Thinking { text: text.into() }
123 }
124
125 #[must_use]
126 pub fn text_delta(delta: impl Into<String>) -> Self {
127 Self::TextDelta {
128 delta: delta.into(),
129 }
130 }
131
132 #[must_use]
133 pub fn text(text: impl Into<String>) -> Self {
134 Self::Text { text: text.into() }
135 }
136
137 #[must_use]
138 pub fn tool_call_start(
139 id: impl Into<String>,
140 name: impl Into<String>,
141 input: serde_json::Value,
142 tier: ToolTier,
143 ) -> Self {
144 Self::ToolCallStart {
145 id: id.into(),
146 name: name.into(),
147 input,
148 tier,
149 }
150 }
151
152 #[must_use]
153 pub fn tool_call_end(
154 id: impl Into<String>,
155 name: impl Into<String>,
156 result: ToolResult,
157 ) -> Self {
158 Self::ToolCallEnd {
159 id: id.into(),
160 name: name.into(),
161 result,
162 }
163 }
164
165 #[must_use]
166 pub const fn done(
167 thread_id: ThreadId,
168 total_turns: usize,
169 total_usage: TokenUsage,
170 duration: Duration,
171 ) -> Self {
172 Self::Done {
173 thread_id,
174 total_turns,
175 total_usage,
176 duration,
177 }
178 }
179
180 #[must_use]
181 pub fn error(message: impl Into<String>, recoverable: bool) -> Self {
182 Self::Error {
183 message: message.into(),
184 recoverable,
185 }
186 }
187
188 #[must_use]
189 pub const fn context_compacted(
190 original_count: usize,
191 new_count: usize,
192 original_tokens: usize,
193 new_tokens: usize,
194 ) -> Self {
195 Self::ContextCompacted {
196 original_count,
197 new_count,
198 original_tokens,
199 new_tokens,
200 }
201 }
202}