1use std::time::Duration;
2
3use thiserror::Error;
4
5#[derive(Debug, Error)]
9pub enum HeyoError {
10 #[error("Missing API key. Pass `api_key` or set HEYO_API_KEY.")]
12 Authentication,
13
14 #[error("{0}")]
16 InvalidArgument(String),
17
18 #[error("not found: {0}")]
20 NotFound(String),
21
22 #[error("api error ({status}): {message}")]
24 Api {
25 status: u16,
26 message: String,
27 body: Option<serde_json::Value>,
28 },
29
30 #[error("timeout after {0:?}: {1}")]
32 Timeout(Duration, String),
33
34 #[error("sandbox {sandbox_id} failed: {reason}")]
36 SandboxFailed {
37 sandbox_id: String,
38 reason: String,
39 },
40
41 #[error("connection error: {0}")]
43 Connection(String),
44
45 #[error("shell session expired{}", .session_id.as_deref().map(|s| format!(" ({})", s)).unwrap_or_default())]
47 SessionExpired { session_id: Option<String> },
48
49 #[error("shell exited with code {0}")]
51 ShellExit(i32),
52
53 #[error("checkin conflict: expected={expected:?} current={current}")]
55 CheckinConflict {
56 expected: Option<i64>,
57 current: i64,
58 },
59}
60
61impl HeyoError {
62 pub(crate) fn invalid(msg: impl Into<String>) -> Self {
63 HeyoError::InvalidArgument(msg.into())
64 }
65 pub(crate) fn api(status: u16, message: impl Into<String>) -> Self {
66 HeyoError::Api {
67 status,
68 message: message.into(),
69 body: None,
70 }
71 }
72 pub(crate) fn api_with_body(
73 status: u16,
74 message: impl Into<String>,
75 body: Option<serde_json::Value>,
76 ) -> Self {
77 HeyoError::Api {
78 status,
79 message: message.into(),
80 body,
81 }
82 }
83}