Skip to main content

a3s_code_core/llm/
error.rs

1//! Error markers shared by LLM clients and the agent retry loop.
2
3use thiserror::Error;
4
5/// A provider error that cannot succeed through an immediate retry.
6///
7/// The message must be safe to show directly to an end user. Provider clients
8/// should use this only for precise terminal conditions, such as an exhausted
9/// account quota, and not for ordinary transient rate limits.
10#[derive(Debug, Error)]
11#[error("{message}")]
12pub struct NonRetryableLlmError {
13    message: String,
14}
15
16impl NonRetryableLlmError {
17    pub fn new(message: impl Into<String>) -> Self {
18        Self {
19            message: message.into(),
20        }
21    }
22}
23
24pub(crate) fn non_retryable_llm_error_message(error: &anyhow::Error) -> Option<&str> {
25    error
26        .downcast_ref::<NonRetryableLlmError>()
27        .map(|error| error.message.as_str())
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33
34    #[test]
35    fn marker_survives_anyhow_context() {
36        let error = anyhow::Error::new(NonRetryableLlmError::new("quota exhausted"))
37            .context("LLM call failed");
38
39        assert_eq!(
40            non_retryable_llm_error_message(&error),
41            Some("quota exhausted")
42        );
43    }
44}