1#[derive(Clone, Debug)]
8pub enum AgentEvent {
9 TurnStart {
11 turn: u32,
13 },
14
15 TextDelta {
17 text: String,
19 },
20
21 ThinkingDelta {
23 text: String,
25 },
26
27 ToolCall {
29 id: String,
31 name: String,
33 input: serde_json::Value,
35 },
36
37 ToolResult {
39 id: String,
41 name: String,
43 output: String,
45 success: bool,
47 },
48
49 TextComplete {
51 text: String,
53 },
54
55 TurnEnd {
57 turn: u32,
59 reason: TurnEndReason,
61 },
62
63 Error {
65 message: String,
67 },
68}
69
70#[derive(Clone, Debug, PartialEq, Eq)]
72pub enum TurnEndReason {
73 EndTurn,
75 ToolUse,
77 MaxTurns,
79 MaxTokens,
81 Error,
83}
84
85pub type EventSender = tokio::sync::mpsc::Sender<AgentEvent>;
87
88pub type EventReceiver = tokio::sync::mpsc::Receiver<AgentEvent>;
90
91pub fn event_channel(buffer: usize) -> (EventSender, EventReceiver) {
93 tokio::sync::mpsc::channel(buffer)
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn turn_end_reason_equality() {
102 assert_eq!(TurnEndReason::EndTurn, TurnEndReason::EndTurn);
103 assert_ne!(TurnEndReason::EndTurn, TurnEndReason::ToolUse);
104 }
105
106 #[tokio::test]
107 async fn event_channel_send_receive() {
108 let (tx, mut rx) = event_channel(8);
109 let send_result = tx.send(AgentEvent::TurnStart { turn: 1 }).await;
110 assert!(send_result.is_ok());
111
112 let event = rx.recv().await;
113 match event {
114 Some(AgentEvent::TurnStart { turn }) => {
115 assert_eq!(turn, 1);
116 }
117 _ => panic!("Expected TurnStart event"),
118 }
119 }
120
121 #[tokio::test]
122 async fn event_channel_text_delta() {
123 let (tx, mut rx) = event_channel(8);
124 let _ = tx
125 .send(AgentEvent::TextDelta {
126 text: "Hello".into(),
127 })
128 .await;
129
130 match rx.recv().await {
131 Some(AgentEvent::TextDelta { text }) => {
132 assert_eq!(text, "Hello");
133 }
134 _ => panic!("Expected TextDelta event"),
135 }
136 }
137
138 #[tokio::test]
139 async fn event_channel_tool_result() {
140 let (tx, mut rx) = event_channel(8);
141 let _ = tx
142 .send(AgentEvent::ToolResult {
143 id: "tool_1".into(),
144 name: "bash".into(),
145 output: "done".into(),
146 success: true,
147 })
148 .await;
149
150 match rx.recv().await {
151 Some(AgentEvent::ToolResult {
152 id,
153 name,
154 output,
155 success,
156 }) => {
157 assert_eq!(id, "tool_1");
158 assert_eq!(name, "bash");
159 assert_eq!(output, "done");
160 assert!(success);
161 }
162 _ => panic!("Expected ToolResult event"),
163 }
164 }
165
166 #[test]
167 fn agent_event_debug() {
168 let event = AgentEvent::Error {
169 message: "test error".into(),
170 };
171 let debug_str = format!("{event:?}");
172 assert!(debug_str.contains("test error"));
173 }
174}