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