修正共享响应处理的 provider 归属

handle_image_response 与 build_failure_audit 接收实际 provider,不再写死 vector-engine

executor 生成 / 编辑路径传入 settings.provider,nanobanana 路径传入 VectorEngine

budget / curl / raw edit 的审计先沿用原常量,待各自按实际 provider 收口
This commit is contained in:
2026-09-19 13:16:03 +08:00
parent 1c950df116
commit 90b77d6bd0
6 changed files with 29 additions and 15 deletions
@@ -1,13 +1,12 @@
use crate::image_provider::{
audit::build_failure_audit,
constants::VECTOR_ENGINE_PROVIDER,
error::PlatformImageError,
image_source::{download_images_from_urls, images_from_base64},
payload::{
extract_b64_images, extract_generation_id, extract_image_urls, find_first_string_by_key,
parse_api_error_message, parse_json_payload,
},
types::GeneratedImages,
types::{GeneratedImages, ImageProvider},
util::{current_utc_micros, is_timeout_message, truncate_raw},
};
use std::time::Instant;
@@ -15,6 +14,7 @@ use std::time::Instant;
pub(crate) async fn handle_image_response(
http_client: &reqwest::Client,
request_url: &str,
provider: ImageProvider,
response_status: u16,
response_text: &str,
image_model: Option<&'static str>,
@@ -26,10 +26,12 @@ pub(crate) async fn handle_image_response(
task_prefix: &str,
request_deadline: Option<Instant>,
) -> Result<GeneratedImages, PlatformImageError> {
let provider_label = provider.as_str();
if !(200..=299).contains(&response_status) {
let message = parse_api_error_message(response_text, failure_context);
let raw_excerpt = truncate_raw(response_text);
let audit = build_failure_audit(
provider_label,
request_url,
failure_context,
"upstream_status",
@@ -46,7 +48,7 @@ pub(crate) async fn handle_image_response(
image_model,
);
tracing::warn!(
provider = VECTOR_ENGINE_PROVIDER,
provider = provider_label,
endpoint = %request_url,
upstream_status = response_status,
timeout = is_timeout_message(message.as_str()) || is_timeout_message(raw_excerpt.as_str()),
@@ -56,7 +58,7 @@ pub(crate) async fn handle_image_response(
"ImageProvider 图片生成上游错误"
);
return Err(PlatformImageError::Upstream {
provider: VECTOR_ENGINE_PROVIDER,
provider: provider_label,
message,
upstream_status: response_status,
raw_excerpt,
@@ -68,6 +70,7 @@ pub(crate) async fn handle_image_response(
Ok(response_json) => response_json,
Err(error) => {
let audit = build_failure_audit(
provider_label,
request_url,
failure_context,
"response_parse",
@@ -84,7 +87,7 @@ pub(crate) async fn handle_image_response(
image_model,
);
tracing::warn!(
provider = VECTOR_ENGINE_PROVIDER,
provider = provider_label,
endpoint = %request_url,
status = response_status,
raw_excerpt = %truncate_raw(response_text),
@@ -118,6 +121,7 @@ pub(crate) async fn handle_image_response(
.audit()
.is_some_and(|audit| audit.failure_stage == "request_budget");
let audit = build_failure_audit(
provider_label,
request_url,
failure_context,
if request_budget_exhausted {
@@ -146,7 +150,7 @@ pub(crate) async fn handle_image_response(
};
generated.actual_prompt = actual_prompt;
tracing::info!(
provider = VECTOR_ENGINE_PROVIDER,
provider = provider_label,
endpoint = %request_url,
image_count = generated.images.len(),
elapsed_ms = download_started_at.elapsed().as_millis() as u64,
@@ -162,6 +166,7 @@ pub(crate) async fn handle_image_response(
let message = format!("{failure_context}ImageProvider 返回的 base64 图片无法解码");
let raw_excerpt = truncate_raw(response_text);
let audit = build_failure_audit(
provider_label,
request_url,
failure_context,
"response_parse",
@@ -178,7 +183,7 @@ pub(crate) async fn handle_image_response(
image_model,
);
tracing::warn!(
provider = VECTOR_ENGINE_PROVIDER,
provider = provider_label,
endpoint = %request_url,
status = response_status,
image_model,
@@ -186,7 +191,7 @@ pub(crate) async fn handle_image_response(
"ImageProvider 图片 base64 解码失败"
);
return Err(PlatformImageError::ResponseParse {
provider: VECTOR_ENGINE_PROVIDER,
provider: provider_label,
message,
raw_excerpt,
audit: Some(audit),
@@ -194,7 +199,7 @@ pub(crate) async fn handle_image_response(
}
generated.actual_prompt = actual_prompt;
tracing::info!(
provider = VECTOR_ENGINE_PROVIDER,
provider = provider_label,
endpoint = %request_url,
image_count = generated.images.len(),
failure_context,
@@ -205,6 +210,7 @@ pub(crate) async fn handle_image_response(
let message = format!("{failure_context}ImageProvider 未返回图片地址");
let audit = build_failure_audit(
provider_label,
request_url,
failure_context,
"missing_image",
@@ -221,14 +227,14 @@ pub(crate) async fn handle_image_response(
image_model,
);
tracing::warn!(
provider = VECTOR_ENGINE_PROVIDER,
provider = provider_label,
endpoint = %request_url,
status = response_status,
raw_excerpt = %truncate_raw(response_text),
"ImageProvider 图片响应未返回图片"
);
Err(PlatformImageError::MissingImage {
provider: VECTOR_ENGINE_PROVIDER,
provider: provider_label,
message,
audit: Some(audit),
})
@@ -1,5 +1,3 @@
use crate::image_provider::constants::VECTOR_ENGINE_PROVIDER;
#[derive(Clone, Debug)]
pub struct PlatformImageFailureAudit {
pub provider: &'static str,
@@ -20,6 +18,7 @@ pub struct PlatformImageFailureAudit {
}
pub(crate) fn build_failure_audit(
provider: &'static str,
request_url: &str,
operation: &str,
failure_stage: &'static str,
@@ -36,7 +35,7 @@ pub(crate) fn build_failure_audit(
image_model: Option<&'static str>,
) -> PlatformImageFailureAudit {
PlatformImageFailureAudit {
provider: VECTOR_ENGINE_PROVIDER,
provider,
endpoint: request_url.to_string(),
operation: operation.to_string(),
failure_stage,
@@ -61,6 +61,7 @@ pub(crate) fn request_budget_exhausted_error(
const ERROR_SOURCE: &str = "external request deadline elapsed";
let message = format!("{operation}:外部图片请求执行预算已耗尽");
let audit = build_failure_audit(
VECTOR_ENGINE_PROVIDER,
request_url,
operation,
"request_budget",
@@ -27,7 +27,7 @@ use crate::image_provider::{
resolve_image_provider,
},
response::handle_image_response,
types::{GeneratedImages, ImageProviderSettings, ReferenceImage},
types::{GeneratedImages, ImageProvider, ImageProviderSettings, ReferenceImage},
util::truncate_raw,
};
@@ -219,6 +219,7 @@ pub async fn create_image_generation_with_model(
match handle_image_response(
http_client,
request_url.as_str(),
settings.provider,
response_status,
response_text.as_str(),
auditable_image_model(upstream_model),
@@ -407,6 +408,7 @@ pub async fn create_nanobanana_generate_content(
handle_image_response(
http_client,
request_url.as_str(),
ImageProvider::VectorEngine,
response_status,
response_text.as_str(),
None,
@@ -658,6 +660,7 @@ pub async fn create_image_edit_with_references_and_model(
match handle_image_response(
http_client,
request_url.as_str(),
settings.provider,
response_status,
response_text.as_str(),
auditable_image_model(upstream_model),
@@ -160,6 +160,7 @@ pub(crate) fn map_curl_error(
let source = error.to_string();
let message = format!("{context}{source}");
let audit = build_failure_audit(
VECTOR_ENGINE_PROVIDER,
request_url,
context,
failure_stage,
@@ -228,6 +228,7 @@ pub async fn create_raw_image_edit(
);
let raw_excerpt = truncate_raw(body.as_str());
let audit = build_failure_audit(
VECTOR_ENGINE_PROVIDER,
url.as_str(),
failure_context,
"upstream_status",
@@ -257,6 +258,7 @@ pub async fn create_raw_image_edit(
let message = format!("{failure_context}:上游响应不是 JSON{error}");
let raw_excerpt = truncate_raw(body.as_str());
let audit = build_failure_audit(
VECTOR_ENGINE_PROVIDER,
url.as_str(),
failure_context,
"response_parse",
@@ -284,6 +286,7 @@ pub async fn create_raw_image_edit(
if b64_images.is_empty() {
let message = format!("{failure_context}:上游未返回 b64_json 图片");
let audit = build_failure_audit(
VECTOR_ENGINE_PROVIDER,
url.as_str(),
failure_context,
"missing_image",
@@ -356,6 +359,7 @@ fn request_error(
"ImageProvider Raw 图片编辑请求失败"
);
let audit = build_failure_audit(
VECTOR_ENGINE_PROVIDER,
url,
context,
failure_stage,