ag_agent/app_server/
error.rs1use crate::app_server_transport::AppServerTransportError;
2
3#[derive(Debug, thiserror::Error)]
9pub enum AppServerError {
10 #[error("{0}")]
12 InterruptedByUser(String),
13
14 #[error("Failed to lock {provider} app-server session map")]
16 LockPoisoned {
17 provider: &'static str,
19 },
20
21 #[error("{0}")]
23 PromptRender(String),
24
25 #[error("{0}")]
27 Provider(String),
28
29 #[error(
31 "{provider} app-server failed, then retry failed after restart: first error: \
32 {first_error}; retry error: {retry_error}"
33 )]
34 RetryExhausted {
35 provider: &'static str,
37 first_error: String,
39 retry_error: String,
41 },
42
43 #[error(transparent)]
45 Transport(#[from] AppServerTransportError),
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51
52 #[test]
53 fn lock_poisoned_display_includes_provider_name() {
54 let error = AppServerError::LockPoisoned { provider: "Codex" };
56
57 let display = error.to_string();
59
60 assert_eq!(display, "Failed to lock Codex app-server session map");
62 }
63
64 #[test]
65 fn interrupted_by_user_display_shows_message() {
66 let error = AppServerError::InterruptedByUser("[Stopped]".to_string());
68
69 assert_eq!(error.to_string(), "[Stopped]");
71 }
72
73 #[test]
74 fn prompt_render_display_shows_message() {
75 let error = AppServerError::PromptRender("template syntax error".to_string());
77
78 assert_eq!(error.to_string(), "template syntax error");
80 }
81
82 #[test]
83 fn provider_display_shows_message() {
84 let error = AppServerError::Provider("runtime crashed".to_string());
86
87 assert_eq!(error.to_string(), "runtime crashed");
89 }
90
91 #[test]
92 fn retry_exhausted_display_includes_both_errors() {
93 let error = AppServerError::RetryExhausted {
95 provider: "Codex",
96 first_error: "connection reset".to_string(),
97 retry_error: "timeout".to_string(),
98 };
99
100 let display = error.to_string();
102
103 assert_eq!(
105 display,
106 "Codex app-server failed, then retry failed after restart: first error: connection \
107 reset; retry error: timeout"
108 );
109 }
110
111 #[test]
112 fn transport_display_delegates_to_inner_error() {
113 let error = AppServerError::Transport(AppServerTransportError::ProcessTerminated);
115
116 assert_eq!(
118 error.to_string(),
119 "App-server terminated before sending expected response"
120 );
121 }
122
123 #[test]
124 fn transport_from_conversion_wraps_transport_error() {
125 let transport_error = AppServerTransportError::Timeout {
127 response_id: "init-1".to_string(),
128 timeout_seconds: 300,
129 };
130
131 let error: AppServerError = transport_error.into();
133
134 assert!(matches!(error, AppServerError::Transport(_)));
136 }
137}