gproxy_protocol/transform/claude/count_tokens/gemini/
request.rs1use crate::claude::count_tokens::request::ClaudeCountTokensRequest;
2use crate::claude::count_tokens::types::BetaMessageRole;
3use crate::gemini::count_tokens::request::{
4 GeminiCountTokensRequest, PathParameters, QueryParameters, RequestBody, RequestHeaders,
5};
6use crate::gemini::count_tokens::types::{
7 GeminiContent, GeminiContentRole, GeminiGenerateContentRequest, GeminiGenerationConfig,
8 GeminiPart, HttpMethod,
9};
10use crate::transform::claude::count_tokens::utils::{
11 beta_message_content_to_text, claude_model_to_string,
12};
13use crate::transform::claude::generate_content::gemini::utils::{
14 gemini_system_instruction_from_claude, gemini_thinking_config_from_claude,
15 gemini_tool_config_from_claude, gemini_tools_from_claude,
16};
17use crate::transform::claude::model_list::gemini::utils::ensure_models_prefix;
18use crate::transform::utils::TransformError;
19
20impl TryFrom<ClaudeCountTokensRequest> for GeminiCountTokensRequest {
21 type Error = TransformError;
22
23 fn try_from(value: ClaudeCountTokensRequest) -> Result<Self, TransformError> {
24 let model = ensure_models_prefix(&claude_model_to_string(&value.body.model));
25 let contents = value
26 .body
27 .messages
28 .into_iter()
29 .map(|message| GeminiContent {
30 parts: vec![GeminiPart {
31 text: Some(beta_message_content_to_text(&message.content)),
32 ..GeminiPart::default()
33 }],
34 role: Some(match message.role {
35 BetaMessageRole::User => GeminiContentRole::User,
36 BetaMessageRole::Assistant => GeminiContentRole::Model,
37 }),
38 })
39 .collect::<Vec<_>>();
40 let tools = gemini_tools_from_claude(value.body.tools, false);
41 let tool_config = gemini_tool_config_from_claude(value.body.tool_choice);
42 let thinking_config = gemini_thinking_config_from_claude(
43 value.body.thinking,
44 value
45 .body
46 .output_config
47 .as_ref()
48 .and_then(|config| config.effort.as_ref()),
49 );
50 let system_instruction = gemini_system_instruction_from_claude(value.body.system);
51 let json_output_requested = value
52 .body
53 .output_config
54 .as_ref()
55 .and_then(|config| config.format.as_ref())
56 .is_some();
57 let generation_config = if thinking_config.is_some() || json_output_requested {
58 Some(GeminiGenerationConfig {
59 response_mime_type: if json_output_requested {
60 Some("application/json".to_string())
61 } else {
62 None
63 },
64 thinking_config,
65 ..GeminiGenerationConfig::default()
66 })
67 } else {
68 None
69 };
70
71 Ok(Self {
72 method: HttpMethod::Post,
73 path: PathParameters {
74 model: model.clone(),
75 },
76 query: QueryParameters::default(),
77 headers: RequestHeaders::default(),
78 body: RequestBody {
79 contents: None,
80 generate_content_request: Some(GeminiGenerateContentRequest {
81 model,
82 contents,
83 tools,
84 tool_config,
85 safety_settings: None,
86 system_instruction,
87 generation_config,
88 cached_content: None,
89 }),
90 },
91 })
92 }
93}