Skip to main content

brainwires_agent_network/network/
event.rs

1use serde::{Deserialize, Serialize};
2
3use super::envelope::MessageEnvelope;
4use super::error::NetworkError;
5use crate::identity::AgentIdentity;
6
7/// The connection state of a transport.
8#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
9pub enum ConnectionState {
10    /// Transport is disconnected.
11    Disconnected,
12    /// Transport is attempting to connect.
13    Connecting,
14    /// Transport is connected and ready.
15    Connected,
16    /// Transport is reconnecting after a failure.
17    Reconnecting,
18}
19
20/// A transport type identifier for events.
21#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
22pub enum TransportType {
23    /// Local Unix socket IPC.
24    Ipc,
25    /// Remote bridge (Supabase Realtime / HTTP polling).
26    Remote,
27    /// Direct TCP peer-to-peer.
28    Tcp,
29    /// A2A protocol transport.
30    A2a,
31    /// Pub/Sub event-driven transport.
32    PubSub,
33    /// Custom transport with a user-defined identifier.
34    Custom(String),
35}
36
37/// Events emitted by the networking stack.
38///
39/// Subscribe to these via `NetworkManager::subscribe()` to react to
40/// peer changes, incoming messages, and connection state transitions.
41#[derive(Debug, Clone)]
42pub enum NetworkEvent {
43    /// A new peer was discovered or joined the network.
44    PeerJoined(AgentIdentity),
45    /// A peer left the network or became unreachable.
46    PeerLeft(uuid::Uuid),
47    /// A message was received from the network.
48    MessageReceived(MessageEnvelope),
49    /// A transport's connection state changed.
50    ConnectionStateChanged {
51        /// Which transport changed.
52        transport: TransportType,
53        /// The new state.
54        state: ConnectionState,
55    },
56    /// A network-level error occurred.
57    Error(NetworkError),
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63    use uuid::Uuid;
64
65    #[test]
66    fn connection_state_equality() {
67        assert_eq!(ConnectionState::Connected, ConnectionState::Connected);
68        assert_ne!(ConnectionState::Connected, ConnectionState::Disconnected);
69    }
70
71    #[test]
72    fn transport_type_equality() {
73        assert_eq!(TransportType::Ipc, TransportType::Ipc);
74        assert_ne!(TransportType::Ipc, TransportType::Tcp);
75        assert_eq!(
76            TransportType::Custom("nats".into()),
77            TransportType::Custom("nats".into())
78        );
79    }
80
81    #[test]
82    fn transport_type_serde_roundtrip() {
83        let types = vec![
84            TransportType::Ipc,
85            TransportType::Remote,
86            TransportType::Tcp,
87            TransportType::A2a,
88            TransportType::PubSub,
89            TransportType::Custom("redis".into()),
90        ];
91        for t in types {
92            let json = serde_json::to_string(&t).unwrap();
93            let deserialized: TransportType = serde_json::from_str(&json).unwrap();
94            assert_eq!(deserialized, t);
95        }
96    }
97
98    #[test]
99    fn network_event_variants_constructible() {
100        let identity = AgentIdentity::new("test");
101        let _ = NetworkEvent::PeerJoined(identity);
102        let _ = NetworkEvent::PeerLeft(Uuid::new_v4());
103        let _ = NetworkEvent::ConnectionStateChanged {
104            transport: TransportType::Tcp,
105            state: ConnectionState::Connected,
106        };
107        let _ = NetworkEvent::Error(NetworkError::Timeout("5s".into()));
108    }
109}