Skip to main content

agent_tui_usecases/usecases/ports/
errors.rs

1//! Use case error types.
2
3use std::error::Error as StdError;
4use thiserror::Error;
5
6type ErrorSource = Box<dyn StdError + Send + Sync + 'static>;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum SpawnErrorKind {
10    NotFound,
11    PermissionDenied,
12    Other,
13}
14
15#[derive(Error, Debug)]
16pub enum TerminalError {
17    #[error("Failed to open terminal: {reason}")]
18    Open {
19        reason: String,
20        #[source]
21        source: Option<ErrorSource>,
22    },
23    #[error("Failed to spawn process: {reason}")]
24    Spawn {
25        reason: String,
26        kind: SpawnErrorKind,
27    },
28    #[error("Failed to write to terminal: {reason}")]
29    Write {
30        reason: String,
31        #[source]
32        source: Option<ErrorSource>,
33    },
34    #[error("Failed to read from terminal: {reason}")]
35    Read {
36        reason: String,
37        #[source]
38        source: Option<ErrorSource>,
39    },
40    #[error("Failed to resize terminal: {reason}")]
41    Resize {
42        reason: String,
43        #[source]
44        source: Option<ErrorSource>,
45    },
46}
47
48impl TerminalError {
49    pub fn operation(&self) -> &'static str {
50        match self {
51            TerminalError::Open { .. } => "open",
52            TerminalError::Spawn { .. } => "spawn",
53            TerminalError::Write { .. } => "write",
54            TerminalError::Read { .. } => "read",
55            TerminalError::Resize { .. } => "resize",
56        }
57    }
58
59    pub fn reason(&self) -> &str {
60        match self {
61            TerminalError::Open { reason, .. }
62            | TerminalError::Write { reason, .. }
63            | TerminalError::Read { reason, .. }
64            | TerminalError::Resize { reason, .. } => reason,
65            TerminalError::Spawn { reason, .. } => reason,
66        }
67    }
68
69    pub fn spawn_kind(&self) -> Option<SpawnErrorKind> {
70        match self {
71            TerminalError::Spawn { kind, .. } => Some(*kind),
72            _ => None,
73        }
74    }
75
76    pub fn is_retryable(&self) -> bool {
77        matches!(
78            self,
79            TerminalError::Read { .. } | TerminalError::Write { .. }
80        )
81    }
82}
83
84#[derive(Error, Debug)]
85pub enum SessionError {
86    #[error("Session not found: {0}")]
87    NotFound(String),
88    #[error("Session not running: {session_id}")]
89    NotRunning { session_id: String },
90    #[error("Session already exists: {0}")]
91    AlreadyExists(String),
92    #[error("No active session")]
93    NoActiveSession,
94    #[error("Terminal error: {0}")]
95    Terminal(#[from] TerminalError),
96    #[error("Invalid key: {0}")]
97    InvalidKey(String),
98    #[error("Invalid input for {field}: {reason}")]
99    InvalidInput { field: String, reason: String },
100    #[error("Session limit reached: maximum {0} sessions allowed")]
101    LimitReached(usize),
102    #[error("Persistence error during {operation}: {reason}")]
103    Persistence {
104        operation: String,
105        reason: String,
106        #[source]
107        source: Option<ErrorSource>,
108    },
109}