use thiserror::Error;
#[derive(Debug, Clone)]
pub struct CastIssue {
pub pointer: String,
pub message: String,
}
#[derive(Debug, Error)]
pub enum CastError {
#[error("invalid JSON after repair: {0}")]
InvalidJson(String),
#[error("schema validation failed ({} issue(s))", issues.len())]
Invalid {
issues: Vec<CastIssue>,
},
#[error("retry budget exhausted after {attempts} attempts; last error: {last}")]
RetryExhausted {
attempts: usize,
last: String,
},
#[error("retry function failed: {0}")]
RetryFailed(String),
#[error("invalid schema: {0}")]
InvalidSchema(String),
}
impl CastError {
pub fn for_llm(&self) -> Option<String> {
match self {
CastError::Invalid { issues } => {
let mut s = String::from("Output rejected. Fix and try again:\n");
for i in issues {
s.push_str(" - ");
if !i.pointer.is_empty() {
s.push_str(&i.pointer);
s.push_str(": ");
}
s.push_str(&i.message);
s.push('\n');
}
Some(s.trim_end().to_string())
}
CastError::InvalidJson(msg) => Some(format!(
"Output was not valid JSON. Return only a JSON object matching the schema. Parser said: {msg}"
)),
_ => None,
}
}
}