Add Google Gemini provider support
- Add GeminiProvider with streaming and native tool calling - Support gemini-2.5-pro, gemini-2.0-flash, gemini-1.5-pro/flash models - Model-specific context window detection (1M-2M tokens) - Message conversion: assistant -> model role mapping - System messages extracted to system_instruction field - Tool schema conversion with functionCall/functionResponse parts - SSE streaming with JSON array buffer parsing - 8 unit tests for conversion and parsing logic - Register provider in g3-core and validate in g3-cli
This commit is contained in:
@@ -46,6 +46,10 @@ pub struct ProvidersConfig {
|
||||
#[serde(default)]
|
||||
pub embedded: HashMap<String, EmbeddedConfig>,
|
||||
|
||||
/// Named Gemini provider configs
|
||||
#[serde(default)]
|
||||
pub gemini: HashMap<String, GeminiConfig>,
|
||||
|
||||
/// Multiple named OpenAI-compatible providers (e.g., openrouter, groq, etc.)
|
||||
#[serde(default)]
|
||||
pub openai_compatible: HashMap<String, OpenAIConfig>,
|
||||
@@ -92,6 +96,14 @@ pub struct EmbeddedConfig {
|
||||
pub threads: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct GeminiConfig {
|
||||
pub api_key: String,
|
||||
pub model: String,
|
||||
pub max_tokens: Option<u32>,
|
||||
pub temperature: Option<f32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AgentConfig {
|
||||
pub max_context_length: Option<u32>,
|
||||
@@ -230,6 +242,7 @@ impl Default for Config {
|
||||
openai: HashMap::new(),
|
||||
databricks: databricks_configs,
|
||||
embedded: HashMap::new(),
|
||||
gemini: HashMap::new(),
|
||||
openai_compatible: HashMap::new(),
|
||||
},
|
||||
agent: AgentConfig {
|
||||
@@ -445,11 +458,20 @@ impl Config {
|
||||
);
|
||||
}
|
||||
}
|
||||
"gemini" => {
|
||||
if !self.providers.gemini.contains_key(config_name) {
|
||||
anyhow::bail!(
|
||||
"Provider config 'gemini.{}' not found. Available: {:?}",
|
||||
config_name,
|
||||
self.providers.gemini.keys().collect::<Vec<_>>()
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Check openai_compatible providers
|
||||
if !self.providers.openai_compatible.contains_key(provider_type) {
|
||||
anyhow::bail!(
|
||||
"Unknown provider type '{}'. Valid types: anthropic, openai, databricks, embedded, or openai_compatible names",
|
||||
"Unknown provider type '{}'. Valid types: anthropic, openai, databricks, embedded, gemini, or openai_compatible names",
|
||||
provider_type
|
||||
);
|
||||
}
|
||||
@@ -550,6 +572,18 @@ impl Config {
|
||||
));
|
||||
}
|
||||
}
|
||||
"gemini" => {
|
||||
if let Some(ref mut gemini_config) =
|
||||
config.providers.gemini.get_mut(&config_name)
|
||||
{
|
||||
gemini_config.model = model;
|
||||
} else {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Provider config 'gemini.{}' not found.",
|
||||
config_name
|
||||
));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Check openai_compatible
|
||||
if let Some(ref mut compat_config) =
|
||||
@@ -635,6 +669,11 @@ impl Config {
|
||||
self.providers.embedded.get(name)
|
||||
}
|
||||
|
||||
/// Get Gemini config by name
|
||||
pub fn get_gemini_config(&self, name: &str) -> Option<&GeminiConfig> {
|
||||
self.providers.gemini.get(name)
|
||||
}
|
||||
|
||||
/// Get the current default provider's config
|
||||
pub fn get_default_provider_config(&self) -> Result<ProviderConfigRef<'_>> {
|
||||
let (provider_type, config_name) =
|
||||
@@ -665,6 +704,12 @@ impl Config {
|
||||
.get(&config_name)
|
||||
.map(ProviderConfigRef::Embedded)
|
||||
.ok_or_else(|| anyhow::anyhow!("Embedded config '{}' not found", config_name)),
|
||||
"gemini" => self
|
||||
.providers
|
||||
.gemini
|
||||
.get(&config_name)
|
||||
.map(ProviderConfigRef::Gemini)
|
||||
.ok_or_else(|| anyhow::anyhow!("Gemini config '{}' not found", config_name)),
|
||||
_ => self
|
||||
.providers
|
||||
.openai_compatible
|
||||
@@ -684,6 +729,7 @@ pub enum ProviderConfigRef<'a> {
|
||||
OpenAI(&'a OpenAIConfig),
|
||||
Databricks(&'a DatabricksConfig),
|
||||
Embedded(&'a EmbeddedConfig),
|
||||
Gemini(&'a GeminiConfig),
|
||||
OpenAICompatible(&'a OpenAIConfig),
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user