fix(LLM 代理): Chat Completions 透传类型化错误,保留权限码

- resolve_llm_router_client 返回 Result<_, AppError> 而非 String(评审第 17 条)
- load_owner_llm_catalog 的 503 + MODEL_ACCESS_UNAVAILABLE 不再被拍平成「模型目录暂不可用」
- resolve_requested_for 错误改走 agc_model_resolve_error,与 proxy_llm_responses / proxy_llm_messages 契约一致
- LlmConfig / LlmClient 构造失败按 500 返回;调用方直接 llm_error_response 透传
This commit is contained in:
2026-10-04 19:56:16 +08:00
parent b97d559782
commit 6424ad7e75
+18 -13
View File
@@ -187,12 +187,7 @@ pub async fn proxy_llm_chat_completions(
let (llm_client, key_id) =
match resolve_llm_router_client(&state, authenticated.claims().user_id()).await {
Ok((client, key_id)) => (client, key_id),
Err(error) => {
return Err(llm_error_response(
&request_context,
AppError::from_status(StatusCode::SERVICE_UNAVAILABLE).with_message(error),
));
}
Err(error) => return Err(llm_error_response(&request_context, error)),
};
prepare_llm_router_billing(&state, authenticated.claims().user_id())
.await
@@ -1518,16 +1513,20 @@ fn is_responses_terminal_sse_event(event: &str) -> bool {
async fn resolve_llm_router_client(
state: &AppState,
owner_user_id: &str,
) -> Result<(platform_llm::LlmClient, String), String> {
let (base_url, api_key, key_id) = resolve_llm_router_credentials(state, owner_user_id).await?;
let catalog = load_owner_llm_catalog(state, owner_user_id)
) -> Result<(platform_llm::LlmClient, String), AppError> {
let (base_url, api_key, key_id) = resolve_llm_router_credentials(state, owner_user_id)
.await
.map_err(|_| "模型目录暂不可用".to_string())?;
.map_err(|message| {
AppError::from_status(StatusCode::SERVICE_UNAVAILABLE).with_message(message)
})?;
// 目录读失败与会员权限读失败(503 + MODEL_ACCESS_UNAVAILABLE)都保留各自的类型化错误,
// 不再拍平成一句中文,与 `proxy_llm_responses` / `proxy_llm_messages` 的契约一致。
let catalog = load_owner_llm_catalog(state, owner_user_id).await?;
// Chat Completions 的 `model` 恒为账号该档的默认模型,不接收客户端选择。
let model = catalog
.catalog
.resolve_requested_for(None, catalog.access)
.map_err(|error| error.message().to_string())?;
.map_err(agc_model_resolve_error)?;
let config = platform_llm::LlmConfig::new(
platform_llm::LlmProvider::OpenAiCompatible,
base_url.to_string(),
@@ -1537,10 +1536,16 @@ async fn resolve_llm_router_client(
state.config.llm_max_retries,
state.config.llm_retry_backoff_ms,
)
.map_err(|error| error.to_string())?;
.map_err(|error| {
AppError::from_status(StatusCode::INTERNAL_SERVER_ERROR)
.with_message(format!("LLM Router 客户端配置非法:{error}"))
})?;
platform_llm::LlmClient::new(config)
.map(|client| (client, key_id))
.map_err(|error| error.to_string())
.map_err(|error| {
AppError::from_status(StatusCode::INTERNAL_SERVER_ERROR)
.with_message(format!("创建 LLM Router 客户端失败:{error}"))
})
}
async fn resolve_llm_router_credentials(