pub mod model_fetcher;
pub mod openai_compat;
pub mod openai_responses;
pub mod request_overrides;
pub mod responses_debug;
pub mod sse;
pub mod stream_tool_accumulator;
pub mod tool_schema;
use sha2::{Digest, Sha256};
use crate::provider::LLMError;
pub(crate) fn log_identity(value: &str) -> String {
let mut digest = Sha256::new();
digest.update(b"bamboo-provider-operational-log-v1\0");
digest.update(value.as_bytes());
hex::encode(&digest.finalize()[..8])
}
pub(crate) fn http_error_kind(error: &reqwest::Error) -> &'static str {
if error.is_timeout() {
"timeout"
} else if error.is_connect() {
"connect"
} else if error.is_request() {
"request"
} else if error.is_body() {
"body"
} else if error.is_decode() {
"decode"
} else if error.is_status() {
"status"
} else {
"transport"
}
}
pub(crate) fn llm_error_kind(error: &LLMError) -> &'static str {
match error {
LLMError::Http(error) => http_error_kind(error),
LLMError::Json(_) => "json",
LLMError::Stream(_) => "stream",
LLMError::Api(_) => "api",
LLMError::Auth(_) => "auth",
LLMError::RequestFailed(_) => "request_failed",
LLMError::Protocol(_) => "protocol",
}
}
pub(crate) fn looks_like_previous_response_not_found_error(
status: reqwest::StatusCode,
body: &str,
) -> bool {
if !(status == 400 || status == 404) {
return false;
}
let b = body.to_ascii_lowercase();
if b.contains("previous_response_not_found") {
return true;
}
let mentions_previous_response =
b.contains("previous_response_id") || b.contains("previous response");
let indicates_missing =
b.contains("not found") || b.contains("not_found") || b.contains("does not exist");
mentions_previous_response && indicates_missing
}
#[cfg(test)]
mod previous_response_not_found_tests {
use super::looks_like_previous_response_not_found_error as f;
use reqwest::StatusCode;
#[test]
fn fires_on_openai_previous_response_not_found_error() {
let bad = StatusCode::BAD_REQUEST;
assert!(f(
bad,
r#"{"error":{"message":"Previous response with id 'resp_123' not found.","type":"invalid_request_error","param":"previous_response_id","code":"previous_response_not_found"}}"#
));
assert!(f(bad, "Previous response with id 'resp_x' not found."));
assert!(f(bad, "previous_response_id 'resp_x' does not exist"));
assert!(f(StatusCode::NOT_FOUND, "previous_response_not_found"));
}
#[test]
fn does_not_fire_on_unrelated_errors() {
let bad = StatusCode::BAD_REQUEST;
assert!(!f(bad, "The model `gpt-x` does not exist or is not found"));
assert!(!f(bad, "Invalid value for 'previous_response_id'")); assert!(!f(
bad,
"previous_response_id is not supported for this model"
)); assert!(!f(
StatusCode::INTERNAL_SERVER_ERROR,
"previous_response_not_found"
));
assert!(!f(StatusCode::UNAUTHORIZED, "previous response not found"));
}
}
#[cfg(test)]
pub(crate) mod log_privacy_tests;