codetether_agent/
event_stream.rs1pub mod s3_sink;
6
7use anyhow::Result;
8use serde::{Deserialize, Serialize};
9use std::sync::Arc;
10use tokio::sync::broadcast;
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
14#[serde(tag = "type", rename_all = "snake_case")]
15pub enum ChatEvent {
16 UserMessage {
18 content: String,
19 timestamp: i64,
20 },
21 AssistantMessage {
23 content: String,
24 timestamp: i64,
25 },
26 ToolCall {
28 tool_name: String,
29 arguments: serde_json::Value,
30 timestamp: i64,
31 },
32 ToolResult {
34 tool_name: String,
35 result: String,
36 success: bool,
37 timestamp: i64,
38 },
39}
40
41impl ChatEvent {
42 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; 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 pub fn to_json(&self) -> String {
63 serde_json::to_string(self).unwrap_or_default()
64 }
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize)]
69#[serde(tag = "type", rename_all = "snake_case")]
70pub enum Event {
71 ToolStarted {
73 tool_name: String,
74 request_id: String,
75 },
76 ToolCompleted {
78 tool_name: String,
79 request_id: String,
80 success: bool,
81 },
82 AgentMessage {
84 content: String,
85 },
86 Error {
88 message: String,
89 },
90 Chat(ChatEvent),
92}
93
94pub struct EventStream {
96 sender: broadcast::Sender<Event>,
97}
98
99impl EventStream {
100 pub fn new() -> Self {
102 let (sender, _) = broadcast::channel(256);
103 Self { sender }
104 }
105
106 pub fn subscribe(&self) -> broadcast::Receiver<Event> {
108 self.sender.subscribe()
109 }
110
111 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}