Handle context size errors in API responses

When the endpoint returns a context size error, the request should not
be retried as it indicates the request is too large for the model's
context window.

Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
diff --git a/src/api_client.rs b/src/api_client.rs
index 1a1f004..7dc4aa6 100644
--- a/src/api_client.rs
+++ b/src/api_client.rs
@@ -7,8 +7,9 @@
 };
 use crate::conflict_resolver::ConflictResolver;
 use crate::prob;
-use anyhow::{Context, Result};
+use anyhow::{Context, Result, bail};
 use reqwest::Certificate;
+use std::fmt;
 use std::fs::File;
 use std::io::Read;
 use std::time::Duration;
@@ -31,6 +32,19 @@
     pub duration: f64,
 }
 
+#[derive(Debug)]
+pub enum ApiRequestError {
+    ExceedContextSize,
+}
+
+impl fmt::Display for ApiRequestError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            ApiRequestError::ExceedContextSize => write!(f, "Exceed context size"),
+        }
+    }
+}
+
 macro_rules! get_context_field {
     ($endpoint_context:expr, $variant_context:expr, $field:ident, $default:expr) => {{
         let endpoint_value = $endpoint_context
@@ -209,6 +223,18 @@
                         "Failed to parse JSON response"
                     })?;
 
+                // Check for context size error in OpenAI responses
+                if let Some(error) = json_response.get("error")
+                    && let Some(error_type) = error.get("type").and_then(|v| v.as_str())
+                    && error_type == "exceed_context_size_error"
+                {
+                    log::warn!(
+                        "Context size error for endpoint {}. Not retrying.",
+                        self.endpoint.name
+                    );
+                    bail!(ApiRequestError::ExceedContextSize);
+                }
+
                 let content = json_response
                     .get("choices")
                     .and_then(|choices| choices.get(0))
@@ -327,6 +353,20 @@
                         "Failed to parse JSON response"
                     })?;
 
+                // Check for context size error in Anthropic responses
+                if let Some(error) = json_response.get("error")
+                    && let Some(error_type) = error.get("type").and_then(|v| v.as_str())
+                    && error_type == "invalid_request_error"
+                    && let Some(message) = error.get("message").and_then(|v| v.as_str())
+                    && message.contains("Request size exceeds model context window")
+                {
+                    log::warn!(
+                        "Context size error for endpoint {}. Not retrying.",
+                        self.endpoint.name
+                    );
+                    bail!(ApiRequestError::ExceedContextSize);
+                }
+
                 let content = json_response
                     .get("content")
                     .and_then(|choices| choices.get(0))
@@ -618,6 +658,15 @@
                             return Ok(api_response);
                         }
                         Err(e) => {
+                            if let Some(api_error) = e.downcast_ref::<ApiRequestError>() {
+                                match api_error {
+                                    ApiRequestError::ExceedContextSize => {
+                                        // If it's a context size error, don't retry
+                                        self.apply_wait().await;
+                                        return Err(e);
+                                    }
+                                }
+                            }
                             self.apply_delay(&mut delay, max_delay, &e).await;
                             last_error = Some(e);
                         }