use thiserror::Error;
#[derive(Debug, Error)]
pub enum LoopError {
#[error("stream transport error: {0}")]
Stream(#[from] StreamError),
#[error("aborted")]
Aborted,
#[error("fatal tool `{tool}` error: {reason}")]
ToolFatal { tool: String, reason: String },
#[error("cannot continue: {0}")]
InvalidContinuation(String),
#[error(
"empty assistant outcome retry budget exhausted: observed {observed} no-tool assistant stop(s), budget {budget}"
)]
EmptyOutcomeBudgetExhausted { budget: usize, observed: usize },
}
#[derive(Debug, Error)]
pub enum StreamError {
#[error("transient stream error: {0}")]
Transient(String),
#[error("provider rate-limited request: {0}")]
ProviderRateLimited(String),
#[error("zero-output transport error: {0}")]
ZeroOutputTransport(String),
#[error("fatal stream error: {0}")]
Fatal(String),
#[error("empty stream response")]
Empty,
#[error("context overflow: {0}")]
ContextOverflow(String),
}
#[derive(Debug, Error)]
pub enum ToolError {
#[error("tool execution failed: {0}")]
Execution(String),
#[error("tool aborted")]
Aborted,
#[error("fatal tool error: {0}")]
Fatal(String),
}
#[derive(Debug, Error)]
pub enum ToolValidationError {
#[error("invalid arguments for `{tool}`: {reason}")]
InvalidArguments { tool: String, reason: String },
#[error("missing required field `{field}` for `{tool}.{action}`")]
MissingField {
tool: String,
action: String,
field: String,
},
#[error("{0}")]
Other(String),
}