use std::time::Duration;
use crate::agent::Agent;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
#[error("`{bin}` not found on PATH; install it: {hint}")]
NotInstalled {
agent: Agent,
bin: String,
hint: &'static str,
},
#[error("failed to spawn `{bin}`: {source}")]
Spawn {
bin: String,
#[source]
source: std::io::Error,
},
#[error("`{bin}` exceeded its {} s timeout and was killed", timeout.as_secs())]
Timeout {
bin: String,
timeout: Duration,
partial: String,
},
#[error("`{bin}` exited with status {code}: {stderr}")]
Failed {
bin: String,
code: i32,
stderr: String,
},
#[error("`{bin}` was rate limited or hit a usage limit: {message}")]
RateLimited {
bin: String,
message: String,
},
#[error("{agent} does not support {what}")]
Unsupported {
agent: Agent,
what: &'static str,
},
#[error("session `{name}` belongs to {bound}, cannot resume it on {requested}")]
SessionConflict {
name: String,
bound: Agent,
requested: Agent,
},
#[error("session store I/O failed at {path}: {source}")]
Store {
path: String,
#[source]
source: std::io::Error,
},
#[error("could not parse {agent} output: {detail}")]
Parse {
agent: Agent,
detail: String,
},
#[error("the run of `{bin}` was cancelled")]
Cancelled {
bin: String,
},
#[error(
"{what} is {size} bytes, over the {limit} byte command-line budget for {agent}, \
and it has no way to take it off the command line"
)]
CommandLineTooLarge {
agent: Agent,
what: &'static str,
size: usize,
limit: usize,
},
#[error("no Tokio runtime is running; call this from within one")]
NoRuntime,
#[error("the run of `{bin}` was interrupted: {detail}")]
Interrupted {
bin: String,
detail: String,
},
}
impl Error {
#[must_use]
pub fn is_transient(&self) -> bool {
matches!(self, Error::RateLimited { .. } | Error::Timeout { .. })
}
#[must_use]
pub fn is_cancelled(&self) -> bool {
matches!(self, Error::Cancelled { .. })
}
}