feagi_agent/
feagi_agent_error.rs1use feagi_io::FeagiNetworkError;
4use feagi_structures::FeagiDataError;
5use std::error::Error;
6use std::fmt::{Display, Formatter};
7
8#[derive(Debug, Clone)]
10pub enum FeagiAgentError {
11 InitFail(String),
13 ConnectionFailed(String),
15 AuthenticationFailed(String),
17 UnableToDecodeReceivedData(String),
19 UnableToSendData(String),
21 SocketFailure(String),
23 Other(String),
25}
26
27impl Display for FeagiAgentError {
28 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
29 match self {
30 FeagiAgentError::InitFail(msg) => {
31 write!(f, "FeagiAgentError: Init failed: {}", msg)
32 }
33 FeagiAgentError::ConnectionFailed(msg) => {
34 write!(f, "FeagiAgentError: Connection failed: {}", msg)
35 }
36 FeagiAgentError::AuthenticationFailed(msg) => {
37 write!(f, "FeagiAgentError: Authentication failed: {}", msg)
38 }
39 FeagiAgentError::UnableToDecodeReceivedData(msg) => {
40 write!(
41 f,
42 "FeagiAgentError: Unable to decode received data: {}",
43 msg
44 )
45 }
46 FeagiAgentError::UnableToSendData(msg) => {
47 write!(f, "FeagiAgentError: Unable to send data: {}", msg)
48 }
49 FeagiAgentError::SocketFailure(msg) => {
50 write!(f, "FeagiAgentError: Socket failure: {}", msg)
51 }
52 FeagiAgentError::Other(msg) => {
53 write!(f, "FeagiAgentError: {}", msg)
54 }
55 }
56 }
57}
58
59impl Error for FeagiAgentError {
60 fn source(&self) -> Option<&(dyn Error + 'static)> {
61 None
62 }
63}
64
65impl From<FeagiDataError> for FeagiAgentError {
66 fn from(err: FeagiDataError) -> Self {
67 match err {
68 FeagiDataError::DeserializationError(msg) => {
69 FeagiAgentError::UnableToDecodeReceivedData(msg)
70 }
71 FeagiDataError::SerializationError(msg) => FeagiAgentError::UnableToSendData(msg),
72 FeagiDataError::BadParameters(msg) => {
73 FeagiAgentError::Other(format!("Bad parameters: {}", msg))
74 }
75 FeagiDataError::NeuronError(msg) => {
76 FeagiAgentError::Other(format!("Neuron error: {}", msg))
77 }
78 FeagiDataError::InternalError(msg) => {
79 FeagiAgentError::Other(format!("Internal error: {}", msg))
80 }
81 FeagiDataError::ResourceLockedWhileRunning(msg) => {
82 FeagiAgentError::Other(format!("Resource locked: {}", msg))
83 }
84 FeagiDataError::ConstError(msg) => {
85 FeagiAgentError::Other(format!("Const error: {}", msg))
86 }
87 FeagiDataError::NotImplemented => FeagiAgentError::Other("Not implemented".to_string()),
88 }
89 }
90}
91
92pub fn is_transient_zmq_send_would_block(err: &FeagiAgentError) -> bool {
97 match err {
98 FeagiAgentError::UnableToSendData(msg) | FeagiAgentError::SocketFailure(msg) => {
99 msg.contains("Socket would block")
100 }
101 _ => err.to_string().contains("Socket would block"),
102 }
103}
104
105pub fn is_transient_zmq_send_message(message: &str) -> bool {
107 message.contains("Socket would block")
108}
109
110impl From<FeagiNetworkError> for FeagiAgentError {
111 fn from(err: FeagiNetworkError) -> Self {
112 match err {
113 FeagiNetworkError::CannotBind(msg) => {
114 FeagiAgentError::InitFail(format!("Cannot bind: {}", msg))
115 }
116 FeagiNetworkError::CannotUnbind(msg) => {
117 FeagiAgentError::SocketFailure(format!("Cannot unbind: {}", msg))
118 }
119 FeagiNetworkError::CannotConnect(msg) => {
120 FeagiAgentError::ConnectionFailed(format!("Cannot connect: {}", msg))
121 }
122 FeagiNetworkError::CannotDisconnect(msg) => {
123 FeagiAgentError::SocketFailure(format!("Cannot disconnect: {}", msg))
124 }
125 FeagiNetworkError::SendFailed(msg) => FeagiAgentError::UnableToSendData(msg),
126 FeagiNetworkError::ReceiveFailed(msg) => {
127 FeagiAgentError::UnableToDecodeReceivedData(format!("Receive failed: {}", msg))
128 }
129 FeagiNetworkError::InvalidSocketProperties(msg) => {
130 FeagiAgentError::InitFail(format!("Invalid socket properties: {}", msg))
131 }
132 FeagiNetworkError::SocketCreationFailed(msg) => {
133 FeagiAgentError::SocketFailure(format!("Socket creation failed: {}", msg))
134 }
135 FeagiNetworkError::GeneralFailure(msg) => {
136 FeagiAgentError::Other(format!("General failure: {}", msg))
137 }
138 }
139 }
140}
141
142#[cfg(test)]
143mod transient_send_tests {
144 use super::*;
145
146 #[test]
147 fn detects_would_block_in_unable_to_send() {
148 let e = FeagiAgentError::UnableToSendData("Socket would block".to_string());
149 assert!(is_transient_zmq_send_would_block(&e));
150 }
151
152 #[test]
153 fn ignores_other_unable_to_send() {
154 let e =
155 FeagiAgentError::UnableToSendData("Cannot send to inactive sensory socket".to_string());
156 assert!(!is_transient_zmq_send_would_block(&e));
157 }
158
159 #[test]
160 fn message_helper_matches() {
161 assert!(is_transient_zmq_send_message(
162 "FeagiAgentError: Unable to send data: Socket would block"
163 ));
164 assert!(!is_transient_zmq_send_message("connection reset"));
165 }
166}