pub mod s3_sink;
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tokio::sync::broadcast;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ChatEvent {
UserMessage {
content: String,
timestamp: i64,
},
AssistantMessage {
content: String,
timestamp: i64,
},
ToolCall {
tool_name: String,
arguments: serde_json::Value,
timestamp: i64,
},
ToolResult {
tool_name: String,
result: String,
success: bool,
timestamp: i64,
},
}
impl ChatEvent {
pub fn tool_result(
workspace: std::path::PathBuf,
_session_id: String,
tool_name: &str,
success: bool,
_duration_ms: u64,
result: &str,
_message_count: u64,
) -> Self {
let _ = workspace; Self::ToolResult {
tool_name: tool_name.to_string(),
result: result.to_string(),
success,
timestamp: chrono::Utc::now().timestamp(),
}
}
pub fn to_json(&self) -> String {
serde_json::to_string(self).unwrap_or_default()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum Event {
ToolStarted {
tool_name: String,
request_id: String,
},
ToolCompleted {
tool_name: String,
request_id: String,
success: bool,
},
AgentMessage {
content: String,
},
Error {
message: String,
},
Chat(ChatEvent),
}
pub struct EventStream {
sender: broadcast::Sender<Event>,
}
impl EventStream {
pub fn new() -> Self {
let (sender, _) = broadcast::channel(256);
Self { sender }
}
pub fn subscribe(&self) -> broadcast::Receiver<Event> {
self.sender.subscribe()
}
pub fn send(&self, event: Event) -> Result<()> {
self.sender.send(event)?;
Ok(())
}
}
impl Default for EventStream {
fn default() -> Self {
Self::new()
}
}