Skip to main content

codetether_agent/
event_stream.rs

1//! Event streaming module for real-time event propagation
2//!
3//! Provides event streaming capabilities for the CodeTether agent.
4
5pub mod s3_sink;
6
7use anyhow::Result;
8use serde::{Deserialize, Serialize};
9use tokio::sync::broadcast;
10
11/// Chat event types
12#[derive(Debug, Clone, Serialize, Deserialize)]
13#[serde(tag = "type", rename_all = "snake_case")]
14pub enum ChatEvent {
15    /// User message
16    UserMessage { content: String, timestamp: i64 },
17    /// Assistant message
18    AssistantMessage { content: String, timestamp: i64 },
19    /// Tool call
20    ToolCall {
21        tool_name: String,
22        arguments: serde_json::Value,
23        timestamp: i64,
24    },
25    /// Tool result
26    ToolResult {
27        tool_name: String,
28        result: String,
29        success: bool,
30        timestamp: i64,
31    },
32}
33
34impl ChatEvent {
35    /// Create a tool result event
36    pub fn tool_result(
37        workspace: std::path::PathBuf,
38        _session_id: String,
39        tool_name: &str,
40        success: bool,
41        _duration_ms: u64,
42        result: &str,
43        _message_count: u64,
44    ) -> Self {
45        let _ = workspace; // Suppress unused warning
46        Self::ToolResult {
47            tool_name: tool_name.to_string(),
48            result: result.to_string(),
49            success,
50            timestamp: chrono::Utc::now().timestamp(),
51        }
52    }
53
54    /// Convert to JSON string
55    pub fn to_json(&self) -> String {
56        serde_json::to_string(self).unwrap_or_default()
57    }
58}
59
60/// Event types that can be streamed
61#[derive(Debug, Clone, Serialize, Deserialize)]
62#[serde(tag = "type", rename_all = "snake_case")]
63#[allow(dead_code)]
64pub enum Event {
65    /// Tool execution started
66    ToolStarted {
67        tool_name: String,
68        request_id: String,
69    },
70    /// Tool execution completed
71    ToolCompleted {
72        tool_name: String,
73        request_id: String,
74        success: bool,
75    },
76    /// Agent message
77    AgentMessage { content: String },
78    /// Error occurred
79    Error { message: String },
80    /// Chat event
81    Chat(ChatEvent),
82}
83
84/// Event stream handle
85#[allow(dead_code)]
86pub struct EventStream {
87    sender: broadcast::Sender<Event>,
88}
89
90impl EventStream {
91    #[allow(dead_code)]
92    /// Create a new event stream
93    pub fn new() -> Self {
94        let (sender, _) = broadcast::channel(256);
95        Self { sender }
96    }
97
98    #[allow(dead_code)]
99    /// Subscribe to events
100    pub fn subscribe(&self) -> broadcast::Receiver<Event> {
101        self.sender.subscribe()
102    }
103
104    #[allow(dead_code)]
105    /// Send an event
106    pub fn send(&self, event: Event) -> Result<()> {
107        self.sender.send(event)?;
108        Ok(())
109    }
110}
111
112impl Default for EventStream {
113    fn default() -> Self {
114        Self::new()
115    }
116}