cal_core/
websocket.rs

1// File: cal-core/src/websocket.rs
2
3use crate::{agent::{AgentStatus, AgentStatusUpdate}, RecordReference};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
7#[serde(tag = "type", content = "data")]
8pub enum WebSocketMessage {
9    // Authentication (required for WebSocket security)
10    Auth(AuthMessage),
11    AuthResponse(AuthResponse),
12
13    // Agent Status
14    AgentStatus(AgentStatus),
15    AgentStatusUpdate(AgentStatusUpdate),
16
17    // Typing Indicators
18    IsTyping(IsTypingMessage),
19    IsTypingUpdate(IsTypingUpdate),
20
21    // Queue
22    QueueGroup(crate::queue::QueueGroup),
23
24    // Conversation
25    ConversationNotification(crate::conversation::ConversationNotification),
26
27    // System
28    Ping,
29    Pong,
30    Error(ErrorMessage),
31    Reconnect(ReconnectMessage),
32}
33
34// ==================== Authentication Messages ====================
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct AuthMessage {
38    pub token: String,
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct AuthResponse {
43    pub success: bool,
44    pub user_id: Option<String>,
45    pub agent_id: Option<String>,
46    pub permissions: Vec<String>,
47    pub error: Option<String>,
48}
49
50// ==================== Typing Messages ====================
51
52#[derive(Debug, Clone, Serialize, Deserialize)]
53pub struct IsTypingMessage {
54    pub account: RecordReference,
55    pub user: RecordReference,
56    pub agent_name: String,
57    pub from: String,
58    pub action: String, // "typing" or "stopped"
59    pub timestamp: i64,
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct IsTypingUpdate {
64    pub conversation_id: String,
65    pub user_id: String,
66    pub is_typing: bool,
67    pub timestamp: i64,
68}
69
70// ==================== System Messages ====================
71
72#[derive(Debug, Clone, Serialize, Deserialize)]
73pub struct ErrorMessage {
74    pub code: String,
75    pub message: String,
76    pub details: Option<serde_json::Value>,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize)]
80pub struct ReconnectMessage {
81    pub reason: String,
82    pub retry_after: u32, // seconds
83}
84
85// ==================== Helper Implementations ====================
86
87impl WebSocketMessage {
88    pub fn ping() -> Self {
89        WebSocketMessage::Ping
90    }
91
92    pub fn pong() -> Self {
93        WebSocketMessage::Pong
94    }
95
96    pub fn error(code: String, message: String) -> Self {
97        WebSocketMessage::Error(ErrorMessage {
98            code,
99            message,
100            details: None,
101        })
102    }
103
104    pub fn is_ping(&self) -> bool {
105        matches!(self, WebSocketMessage::Ping)
106    }
107
108    pub fn is_pong(&self) -> bool {
109        matches!(self, WebSocketMessage::Pong)
110    }
111}