gproxy_protocol/transform/gemini/model_list/claude/
utils.rs1use http::StatusCode;
2
3use crate::claude::types::{BetaError, BetaErrorResponse, BetaModelInfo};
4use crate::gemini::types::{GeminiApiError, GeminiApiErrorResponse, GeminiModelInfo};
5
6fn ensure_models_prefix(value: &str) -> String {
7 if value.starts_with("models/") {
8 value.to_string()
9 } else {
10 format!("models/{value}")
11 }
12}
13
14fn gemini_status_from_claude_error(error: &BetaError) -> Option<String> {
15 let status = match error {
16 BetaError::InvalidRequest(_) => "INVALID_ARGUMENT",
17 BetaError::Authentication(_) => "UNAUTHENTICATED",
18 BetaError::Billing(_) => "FAILED_PRECONDITION",
19 BetaError::Permission(_) => "PERMISSION_DENIED",
20 BetaError::NotFound(_) => "NOT_FOUND",
21 BetaError::RateLimit(_) => "RESOURCE_EXHAUSTED",
22 BetaError::GatewayTimeout(_) => "DEADLINE_EXCEEDED",
23 BetaError::Api(_) => "INTERNAL",
24 BetaError::Overloaded(_) => "UNAVAILABLE",
25 };
26 Some(status.to_string())
27}
28
29fn claude_error_message(error: &BetaError) -> String {
30 match error {
31 BetaError::InvalidRequest(err) => err.message.clone(),
32 BetaError::Authentication(err) => err.message.clone(),
33 BetaError::Billing(err) => err.message.clone(),
34 BetaError::Permission(err) => err.message.clone(),
35 BetaError::NotFound(err) => err.message.clone(),
36 BetaError::RateLimit(err) => err.message.clone(),
37 BetaError::GatewayTimeout(err) => err.message.clone(),
38 BetaError::Api(err) => err.message.clone(),
39 BetaError::Overloaded(err) => err.message.clone(),
40 }
41}
42
43pub fn gemini_model_info_from_claude_model(model: BetaModelInfo) -> GeminiModelInfo {
44 GeminiModelInfo {
45 name: ensure_models_prefix(&model.id),
46 base_model_id: Some(model.id),
47 version: None,
48 display_name: if model.display_name.is_empty() {
49 None
50 } else {
51 Some(model.display_name)
52 },
53 description: None,
54 input_token_limit: None,
55 output_token_limit: None,
56 supported_generation_methods: None,
57 thinking: None,
58 temperature: None,
59 max_temperature: None,
60 top_p: None,
61 top_k: None,
62 }
63}
64
65pub fn gemini_error_response_from_claude(
66 status_code: StatusCode,
67 body: BetaErrorResponse,
68) -> GeminiApiErrorResponse {
69 GeminiApiErrorResponse {
70 error: GeminiApiError {
71 code: i32::from(status_code.as_u16()),
72 message: claude_error_message(&body.error),
73 status: gemini_status_from_claude_error(&body.error),
74 details: None,
75 },
76 }
77}