Skip to main content

molo_coding/coding/
error.rs

1use crate::harness::ExecutionError;
2use thiserror::Error;
3
4use super::command::CommandError;
5use super::git::GitError;
6use super::instructions::InstructionError;
7use super::search::SearchError;
8use super::workspace::WorkspaceError;
9
10/// Errors returned by typed coding payload adapters and executor routing.
11#[derive(Debug, Error)]
12#[non_exhaustive]
13pub enum CodingError {
14    /// The effect kind does not match the expected coding payload.
15    #[error("unexpected effect kind: {message}")]
16    UnexpectedKind {
17        /// Model-safe explanation.
18        message: String,
19    },
20    /// The effect payload could not be encoded or decoded.
21    #[error("invalid coding payload: {message}")]
22    InvalidPayload {
23        /// Model-safe explanation.
24        message: String,
25    },
26    /// Workspace operation failed.
27    #[error("workspace error: {0}")]
28    Workspace(Box<WorkspaceError>),
29    /// Command operation failed.
30    #[error("command error: {0}")]
31    Command(#[from] CommandError),
32    /// Git inspection failed.
33    #[error("git error: {0}")]
34    Git(#[from] GitError),
35    /// Repository search failed.
36    #[error("search error: {0}")]
37    Search(#[from] SearchError),
38    /// Instruction resolution failed.
39    #[error("instruction error: {0}")]
40    Instruction(#[from] InstructionError),
41}
42
43impl From<WorkspaceError> for CodingError {
44    fn from(error: WorkspaceError) -> Self {
45        Self::Workspace(Box::new(error))
46    }
47}
48
49impl CodingError {
50    /// Builds an invalid-payload error.
51    pub fn invalid_payload(message: impl Into<String>) -> Self {
52        Self::InvalidPayload {
53            message: message.into(),
54        }
55    }
56
57    /// Builds an unexpected-kind error.
58    pub fn unexpected_kind(message: impl Into<String>) -> Self {
59        Self::UnexpectedKind {
60            message: message.into(),
61        }
62    }
63}
64
65impl From<CodingError> for ExecutionError {
66    fn from(error: CodingError) -> Self {
67        match error {
68            CodingError::Command(CommandError::TimedOut { message }) => {
69                ExecutionError::TimedOut(message)
70            }
71            CodingError::Command(CommandError::Cancelled { message }) => {
72                ExecutionError::Cancelled(message)
73            }
74            CodingError::Command(CommandError::UnsupportedPolicy { message }) => {
75                ExecutionError::Denied(message)
76            }
77            CodingError::UnexpectedKind { message } => ExecutionError::Unsupported(message),
78            other => ExecutionError::Failed(other.to_string()),
79        }
80    }
81}