stakpak_shared/models/integrations/
gemini.rs1use crate::models::model_pricing::{ContextAware, ContextPricingTier, ModelContextInfo};
7use serde::{Deserialize, Serialize};
8
9#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
11pub struct GeminiConfig {
12 pub api_endpoint: Option<String>,
13 pub api_key: Option<String>,
14}
15
16impl GeminiConfig {
17 pub fn with_api_key(api_key: impl Into<String>) -> Self {
19 Self {
20 api_key: Some(api_key.into()),
21 api_endpoint: None,
22 }
23 }
24
25 pub fn from_provider_auth(auth: &crate::models::auth::ProviderAuth) -> Option<Self> {
27 match auth {
28 crate::models::auth::ProviderAuth::Api { key } => Some(Self::with_api_key(key)),
29 crate::models::auth::ProviderAuth::OAuth { .. } => None, }
31 }
32
33 pub fn with_provider_auth(mut self, auth: &crate::models::auth::ProviderAuth) -> Option<Self> {
35 match auth {
36 crate::models::auth::ProviderAuth::Api { key } => {
37 self.api_key = Some(key.clone());
38 Some(self)
39 }
40 crate::models::auth::ProviderAuth::OAuth { .. } => None,
41 }
42 }
43}
44
45#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
47pub enum GeminiModel {
48 #[default]
49 #[serde(rename = "gemini-3-pro-preview")]
50 Gemini3Pro,
51 #[serde(rename = "gemini-3-flash-preview")]
52 Gemini3Flash,
53 #[serde(rename = "gemini-2.5-pro")]
54 Gemini25Pro,
55 #[serde(rename = "gemini-2.5-flash")]
56 Gemini25Flash,
57 #[serde(rename = "gemini-2.5-flash-lite")]
58 Gemini25FlashLite,
59}
60
61impl std::fmt::Display for GeminiModel {
62 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63 match self {
64 GeminiModel::Gemini3Pro => write!(f, "gemini-3-pro-preview"),
65 GeminiModel::Gemini3Flash => write!(f, "gemini-3-flash-preview"),
66 GeminiModel::Gemini25Pro => write!(f, "gemini-2.5-pro"),
67 GeminiModel::Gemini25Flash => write!(f, "gemini-2.5-flash"),
68 GeminiModel::Gemini25FlashLite => write!(f, "gemini-2.5-flash-lite"),
69 }
70 }
71}
72
73impl GeminiModel {
74 pub fn from_string(s: &str) -> Result<Self, String> {
75 serde_json::from_value(serde_json::Value::String(s.to_string()))
76 .map_err(|_| "Failed to deserialize Gemini model".to_string())
77 }
78}
79
80impl ContextAware for GeminiModel {
81 fn context_info(&self) -> ModelContextInfo {
82 match self {
83 GeminiModel::Gemini3Pro => ModelContextInfo {
84 max_tokens: 1_000_000,
85 pricing_tiers: vec![
86 ContextPricingTier {
87 label: "<200k tokens".to_string(),
88 input_cost_per_million: 2.0,
89 output_cost_per_million: 12.0,
90 upper_bound: Some(200_000),
91 },
92 ContextPricingTier {
93 label: ">200k tokens".to_string(),
94 input_cost_per_million: 4.0,
95 output_cost_per_million: 18.0,
96 upper_bound: None,
97 },
98 ],
99 approach_warning_threshold: 0.8,
100 },
101 GeminiModel::Gemini25Pro => ModelContextInfo {
102 max_tokens: 1_000_000,
103 pricing_tiers: vec![
104 ContextPricingTier {
105 label: "<200k tokens".to_string(),
106 input_cost_per_million: 1.25,
107 output_cost_per_million: 10.0,
108 upper_bound: Some(200_000),
109 },
110 ContextPricingTier {
111 label: ">200k tokens".to_string(),
112 input_cost_per_million: 2.50,
113 output_cost_per_million: 15.0,
114 upper_bound: None,
115 },
116 ],
117 approach_warning_threshold: 0.8,
118 },
119 GeminiModel::Gemini25Flash => ModelContextInfo {
120 max_tokens: 1_000_000,
121 pricing_tiers: vec![ContextPricingTier {
122 label: "Standard".to_string(),
123 input_cost_per_million: 0.30,
124 output_cost_per_million: 2.50,
125 upper_bound: None,
126 }],
127 approach_warning_threshold: 0.8,
128 },
129 GeminiModel::Gemini3Flash => ModelContextInfo {
130 max_tokens: 1_000_000,
131 pricing_tiers: vec![ContextPricingTier {
132 label: "Standard".to_string(),
133 input_cost_per_million: 0.50,
134 output_cost_per_million: 3.0,
135 upper_bound: None,
136 }],
137 approach_warning_threshold: 0.8,
138 },
139 GeminiModel::Gemini25FlashLite => ModelContextInfo {
140 max_tokens: 1_000_000,
141 pricing_tiers: vec![ContextPricingTier {
142 label: "Standard".to_string(),
143 input_cost_per_million: 0.1,
144 output_cost_per_million: 0.4,
145 upper_bound: None,
146 }],
147 approach_warning_threshold: 0.8,
148 },
149 }
150 }
151
152 fn model_name(&self) -> String {
153 match self {
154 GeminiModel::Gemini3Pro => "Gemini 3 Pro".to_string(),
155 GeminiModel::Gemini3Flash => "Gemini 3 Flash".to_string(),
156 GeminiModel::Gemini25Pro => "Gemini 2.5 Pro".to_string(),
157 GeminiModel::Gemini25Flash => "Gemini 2.5 Flash".to_string(),
158 GeminiModel::Gemini25FlashLite => "Gemini 2.5 Flash Lite".to_string(),
159 }
160 }
161}