#[derive(Clone, Debug)]
pub enum AgentEvent {
TurnStart {
turn: u32,
},
TextDelta {
text: String,
},
ThinkingDelta {
text: String,
},
ToolCall {
id: String,
name: String,
input: serde_json::Value,
},
ToolResult {
id: String,
name: String,
output: String,
success: bool,
},
TextComplete {
text: String,
},
TurnEnd {
turn: u32,
reason: TurnEndReason,
},
Error {
message: String,
},
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TurnEndReason {
EndTurn,
ToolUse,
MaxTurns,
MaxTokens,
Error,
}
pub type EventSender = tokio::sync::mpsc::Sender<AgentEvent>;
pub type EventReceiver = tokio::sync::mpsc::Receiver<AgentEvent>;
pub fn event_channel(buffer: usize) -> (EventSender, EventReceiver) {
tokio::sync::mpsc::channel(buffer)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn turn_end_reason_equality() {
assert_eq!(TurnEndReason::EndTurn, TurnEndReason::EndTurn);
assert_ne!(TurnEndReason::EndTurn, TurnEndReason::ToolUse);
}
#[tokio::test]
async fn event_channel_send_receive() {
let (tx, mut rx) = event_channel(8);
let send_result = tx.send(AgentEvent::TurnStart { turn: 1 }).await;
assert!(send_result.is_ok());
let event = rx.recv().await;
match event {
Some(AgentEvent::TurnStart { turn }) => {
assert_eq!(turn, 1);
}
_ => panic!("Expected TurnStart event"),
}
}
#[tokio::test]
async fn event_channel_text_delta() {
let (tx, mut rx) = event_channel(8);
let _ = tx
.send(AgentEvent::TextDelta {
text: "Hello".into(),
})
.await;
match rx.recv().await {
Some(AgentEvent::TextDelta { text }) => {
assert_eq!(text, "Hello");
}
_ => panic!("Expected TextDelta event"),
}
}
#[tokio::test]
async fn event_channel_tool_result() {
let (tx, mut rx) = event_channel(8);
let _ = tx
.send(AgentEvent::ToolResult {
id: "tool_1".into(),
name: "bash".into(),
output: "done".into(),
success: true,
})
.await;
match rx.recv().await {
Some(AgentEvent::ToolResult {
id,
name,
output,
success,
}) => {
assert_eq!(id, "tool_1");
assert_eq!(name, "bash");
assert_eq!(output, "done");
assert!(success);
}
_ => panic!("Expected ToolResult event"),
}
}
#[test]
fn agent_event_debug() {
let event = AgentEvent::Error {
message: "test error".into(),
};
let debug_str = format!("{event:?}");
assert!(debug_str.contains("test error"));
}
}