Classify provider budget errors as quota limits
This commit is contained in:
@@ -155,10 +155,13 @@ pub async fn generate_multi_agent_output(
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("[openai] Translator error: {e}");
|
||||
let err = Arc::new(crate::server::server_api::AIApiError::Stream {
|
||||
stream_type: "openai_chat_completions",
|
||||
source: anyhow::anyhow!("{e}"),
|
||||
});
|
||||
let err = Arc::new(
|
||||
crate::server::server_api::AIApiError::Stream {
|
||||
stream_type: "openai_chat_completions",
|
||||
source: anyhow::anyhow!("{e}"),
|
||||
}
|
||||
.into_quota_limit_if_provider_budget_exhausted(),
|
||||
);
|
||||
let (tx, rx) = async_channel::unbounded();
|
||||
let _ = tx.send(Err(err)).await;
|
||||
Ok(Box::pin(rx))
|
||||
|
||||
@@ -48,6 +48,7 @@ fn request_params_with_ask_user_question_enabled(ask_user_question_enabled: bool
|
||||
bedrock_progressive_summary: None,
|
||||
bedrock_tool_result_archive: Vec::new(),
|
||||
bedrock_messages_sent: std::sync::Arc::new(std::sync::Mutex::new(Vec::new())),
|
||||
global_rules: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -205,6 +205,29 @@ impl From<serde_json::Error> for AIApiError {
|
||||
}
|
||||
|
||||
impl AIApiError {
|
||||
/// Turns an upstream provider quota/budget response into a user-facing
|
||||
/// quota error instead of a generic stream failure.
|
||||
pub fn into_quota_limit_if_provider_budget_exhausted(self) -> Self {
|
||||
let AIApiError::Stream { source, .. } = self else {
|
||||
return self;
|
||||
};
|
||||
let message = source.to_string();
|
||||
let lower = message.to_ascii_lowercase();
|
||||
if lower.contains("budget has been exceeded")
|
||||
|| lower.contains("rate limit") && lower.contains("429")
|
||||
{
|
||||
return Self::QuotaLimit {
|
||||
user_display_message: Some(
|
||||
"The AI provider has reached its rate limit or monthly budget. Please try again later or choose another configured model.".to_string(),
|
||||
),
|
||||
};
|
||||
}
|
||||
Self::Stream {
|
||||
stream_type: "provider",
|
||||
source,
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a reqwest error to an AIApiError, using response headers to distinguish
|
||||
/// between different types of 429 errors.
|
||||
fn from_response_error(
|
||||
|
||||
Reference in New Issue
Block a user