167 lines
5.6 KiB
Rust
167 lines
5.6 KiB
Rust
//! # Gemini SDK
|
|
//!
|
|
//! A simple Rust SDK for Google Gemini AI services.
|
|
//!
|
|
//! ## Features
|
|
//!
|
|
//! - **Simple Interface**: Send text + attachments to Gemini AI
|
|
//! - **Type Safety**: Strong typing with compile-time error checking
|
|
//! - **Easy Integration**: Minimal external dependencies
|
|
//!
|
|
//! ## Quick Start
|
|
//!
|
|
//! ```rust,no_run
|
|
//! use gemini_sdk::{GeminiSDK, MessageRequest, Attachment, Agent};
|
|
//!
|
|
//! #[tokio::main]
|
|
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
//! // Initialize SDK
|
|
//! let mut sdk = GeminiSDK::new()?;
|
|
//!
|
|
//! // Create an agent (optional)
|
|
//! let agent = Agent::new("assistant", "Assistant", "You are a helpful assistant");
|
|
//! sdk.add_agent(agent);
|
|
//!
|
|
//! // Send a message with attachment
|
|
//! let request = MessageRequest {
|
|
//! text: "Analyze this image".to_string(),
|
|
//! attachments: vec![Attachment::new("./image.jpg")],
|
|
//! agent_id: Some("assistant".to_string()),
|
|
//! };
|
|
//!
|
|
//! let response = sdk.send_message(request).await?;
|
|
//! println!("Response: {}", response.content);
|
|
//!
|
|
//! Ok(())
|
|
//! }
|
|
//! ```
|
|
|
|
pub mod sdk;
|
|
pub mod agent;
|
|
pub mod attachment;
|
|
pub mod error;
|
|
|
|
// Re-export main types for convenience
|
|
pub use sdk::{GeminiSDK, MessageRequest, MessageResponse};
|
|
pub use agent::Agent;
|
|
pub use attachment::Attachment;
|
|
pub use error::{SDKError, Result};
|
|
|
|
/// SDK version
|
|
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
|
|
|
/// Default configuration for the SDK
|
|
#[derive(Debug, Clone)]
|
|
pub struct GeminiConfig {
|
|
pub base_url: String,
|
|
pub bearer_token: String,
|
|
pub timeout: u64,
|
|
pub model_name: String,
|
|
pub max_retries: u32,
|
|
pub retry_delay: u64,
|
|
pub temperature: f32,
|
|
pub max_tokens: u32,
|
|
pub cloudflare_project_id: String,
|
|
pub cloudflare_gateway_id: String,
|
|
pub google_project_id: String,
|
|
pub regions: Vec<String>,
|
|
}
|
|
|
|
impl Default for GeminiConfig {
|
|
fn default() -> Self {
|
|
Self {
|
|
base_url: "https://bowongai-dev--bowong-ai-video-gemini-fastapi-webapp.modal.run".to_string(),
|
|
bearer_token: "bowong7777".to_string(),
|
|
timeout: 120,
|
|
model_name: "gemini-2.5-pro".to_string(),
|
|
max_retries: 3,
|
|
retry_delay: 2,
|
|
temperature: 0.7,
|
|
max_tokens: 64000,
|
|
cloudflare_project_id: "67720b647ff2b55cf37ba3ef9e677083".to_string(),
|
|
cloudflare_gateway_id: "bowong-dev".to_string(),
|
|
google_project_id: "gen-lang-client-0413414134".to_string(),
|
|
regions: vec![
|
|
"us-central1".to_string(),
|
|
"us-east1".to_string(),
|
|
"europe-west1".to_string(),
|
|
],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl GeminiConfig {
|
|
/// Create configuration from environment variables
|
|
pub fn from_env() -> Self {
|
|
Self {
|
|
base_url: std::env::var("GEMINI_BASE_URL")
|
|
.unwrap_or_else(|_| Self::default().base_url),
|
|
bearer_token: std::env::var("GEMINI_BEARER_TOKEN")
|
|
.unwrap_or_else(|_| Self::default().bearer_token),
|
|
timeout: std::env::var("GEMINI_TIMEOUT")
|
|
.ok()
|
|
.and_then(|s| s.parse().ok())
|
|
.unwrap_or(Self::default().timeout),
|
|
model_name: std::env::var("GEMINI_MODEL_NAME")
|
|
.unwrap_or_else(|_| Self::default().model_name),
|
|
max_retries: std::env::var("GEMINI_MAX_RETRIES")
|
|
.ok()
|
|
.and_then(|s| s.parse().ok())
|
|
.unwrap_or(Self::default().max_retries),
|
|
retry_delay: std::env::var("GEMINI_RETRY_DELAY")
|
|
.ok()
|
|
.and_then(|s| s.parse().ok())
|
|
.unwrap_or(Self::default().retry_delay),
|
|
temperature: std::env::var("GEMINI_TEMPERATURE")
|
|
.ok()
|
|
.and_then(|s| s.parse().ok())
|
|
.unwrap_or(Self::default().temperature),
|
|
max_tokens: std::env::var("GEMINI_MAX_TOKENS")
|
|
.ok()
|
|
.and_then(|s| s.parse().ok())
|
|
.unwrap_or(Self::default().max_tokens),
|
|
cloudflare_project_id: std::env::var("GEMINI_CLOUDFLARE_PROJECT_ID")
|
|
.unwrap_or_else(|_| Self::default().cloudflare_project_id),
|
|
cloudflare_gateway_id: std::env::var("GEMINI_CLOUDFLARE_GATEWAY_ID")
|
|
.unwrap_or_else(|_| Self::default().cloudflare_gateway_id),
|
|
google_project_id: std::env::var("GEMINI_GOOGLE_PROJECT_ID")
|
|
.unwrap_or_else(|_| Self::default().google_project_id),
|
|
regions: std::env::var("GEMINI_REGIONS")
|
|
.ok()
|
|
.map(|s| s.split(',').map(|s| s.trim().to_string()).collect())
|
|
.unwrap_or_else(|| Self::default().regions),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_config_default() {
|
|
let config = GeminiConfig::default();
|
|
assert!(!config.base_url.is_empty());
|
|
assert!(!config.bearer_token.is_empty());
|
|
assert!(config.timeout > 0);
|
|
assert!(!config.model_name.is_empty());
|
|
assert!(config.max_retries > 0);
|
|
assert!(config.temperature >= 0.0 && config.temperature <= 2.0);
|
|
assert!(config.max_tokens > 0);
|
|
assert!(!config.regions.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn test_config_from_env() {
|
|
// Test that from_env doesn't panic and returns valid config
|
|
let config = GeminiConfig::from_env();
|
|
assert!(!config.base_url.is_empty());
|
|
assert!(!config.bearer_token.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn test_version() {
|
|
assert!(!VERSION.is_empty());
|
|
}
|
|
}
|