forge-provider-google
Google Gemini provider for the Forge SDK — implements the LanguageModel trait for Google Generative Language API
Google Gemini provider for the Forge SDK — implements the LanguageModel trait for Google Generative Language API
Package contract
| Field | Value |
|---|---|
| Language | rust |
| Source version | 0.2.0 |
| Manifest | forge-rs/crates/forge-provider-google/Cargo.toml |
| Source files | 7 |
| Evidence | Source reference; registry publication and runtime conformance are separate checks |
Import boundary
use forge_provider_google;Use a source checkout or your verified private registry. Manifest coordinates identify the package; they do not establish that a public registry release exists.
Crate boundary
The following entries are taken from src/lib.rs. Feature conditions in the exact source still apply.
#[cfg(not(target_arch = "wasm32"))]
pub mod client;
#[cfg(not(target_arch = "wasm32"))]
pub mod config;
pub mod error;
#[cfg(not(target_arch = "wasm32"))]
pub mod model;
#[cfg(not(target_arch = "wasm32"))]
pub mod sse;
pub mod types;
#[cfg(not(target_arch = "wasm32"))]
pub use config::{GoogleConfig, GoogleConfigBuilder};
pub use error::GoogleError;
#[cfg(not(target_arch = "wasm32"))]
pub use model::GoogleLanguageModel;Source reference
Download package reference JSON. Each original source file and generated declaration artifact has its own SHA-256 digest. Function bodies and constant values are omitted from downloads. These are source declaration inventories, not compiler-resolved rustdoc, TypeDoc, DocC, or Dokka output. Private modules can contain public declarations that are not reachable through the package boundary; consult the entry point before importing.
client.rs
Read declaration text · 5 declaration entries
#[derive(Clone)]
pub struct GoogleHttpClient {
}
pub fn new(config: GoogleConfig) -> Result<Self, GoogleError>;
pub async fn generate_content(
&self,
model: &str,
request: &GenerateContentRequest,
) -> Result<GenerateContentResponse, GoogleError>;
pub async fn stream_generate_content(
&self,
model: &str,
request: &GenerateContentRequest,
) -> Result<Vec<u8>, GoogleError>;
pub async fn stream_generate_content_body(
&self,
model: &str,
request: &GenerateContentRequest,
) -> Result<hyper::body::Incoming, GoogleError>;config.rs
Read declaration text · 12 declaration entries
pub const DEFAULT_BASE_URL: &str;
#[derive(Clone)]
pub struct GoogleConfig {
}
pub fn builder(api_key: impl Into<String>) -> GoogleConfigBuilder;
pub fn base_url(&self) -> &str;
pub fn timeout_seconds(&self) -> u64;
pub fn max_retries(&self) -> u32;
pub fn validate(&self) -> Result<(), GoogleError>;
pub struct GoogleConfigBuilder {
}
pub fn base_url(mut self, url: impl Into<String>) -> Self;
pub fn timeout_seconds(mut self, seconds: u64) -> Self;
pub fn max_retries(mut self, retries: u32) -> Self;
pub fn build(self) -> GoogleConfig;error.rs
Read declaration text · 1 declaration entries
#[derive(Debug, Error)]
pub enum GoogleError {
/// The API key was not provided in the configuration.
#[error("Google API key is missing: provide it via GoogleConfig::builder(api_key) or the GOOGLE_API_KEY environment variable")]
MissingApiKey,
/// The model identifier is empty or invalid.
#[error("invalid model identifier '{model_id}': model ID must be a non-empty string (e.g., 'gemini-2.5-pro', 'gemini-2.5-flash')")]
InvalidModelId {
/// The invalid model identifier that was provided.
model_id: String,
},
/// An HTTP request to the Gemini API failed.
#[error("HTTP request to Google Gemini API failed: {reason} (url: {url})")]
HttpError {
/// The URL that was being requested.
url: String,
/// A description of the failure.
reason: String,
},
/// The Gemini API returned a non-success HTTP status code.
#[error("Google Gemini API returned HTTP {status_code}: {body} (model: {model})")]
ApiError {
/// The HTTP status code returned.
status_code: u16,
/// The response body (may contain error details from Google).
body: String,
/// The model that was being called.
model: String,
},
/// The Gemini API response could not be deserialized.
#[error("failed to deserialize Google Gemini API response: {reason} (raw: {raw_body})")]
DeserializationError {
/// A description of what was expected.
reason: String,
/// The raw response body that failed to parse (truncated to 500 chars).
raw_body: String,
},
/// The Gemini API response contained no candidates.
#[error("Google Gemini API returned no candidates for model '{model}': the response was empty or all candidates were filtered")]
EmptyResponse {
/// The model that was called.
model: String,
},
/// An SSE stream event could not be parsed.
#[error("failed to parse SSE stream event: {reason}")]
SseParseError {
/// A description of what went wrong.
reason: String,
},
/// A request timed out.
#[error("request to Google Gemini API timed out after {timeout_seconds}s (model: {model})")]
Timeout {
/// The timeout duration in seconds.
timeout_seconds: u64,
/// The model that was being called.
model: String,
},
/// Message translation failed.
#[error("failed to translate message to Gemini format: {reason}")]
MessageTranslationError {
/// A description of what went wrong.
reason: String,
},
/// The Gemini API indicated content was blocked by safety filters.
#[error("Google Gemini API blocked content for model '{model}': safety filter triggered (finish_reason: SAFETY)")]
SafetyBlocked {
/// The model that was called.
model: String,
},
}lib.rs
Read declaration text · 9 declaration entries
#[cfg(not(target_arch = "wasm32"))]
pub mod client;
#[cfg(not(target_arch = "wasm32"))]
pub mod config;
pub mod error;
#[cfg(not(target_arch = "wasm32"))]
pub mod model;
#[cfg(not(target_arch = "wasm32"))]
pub mod sse;
pub mod types;
#[cfg(not(target_arch = "wasm32"))]
pub use config::{GoogleConfig, GoogleConfigBuilder};
pub use error::GoogleError;
#[cfg(not(target_arch = "wasm32"))]
pub use model::GoogleLanguageModel;model.rs
Read declaration text · 2 declaration entries
pub struct GoogleLanguageModel {
}
pub fn new(model_id: String, config: GoogleConfig) -> Result<Self, GoogleError>;sse.rs
Read declaration text · 6 declaration entries
pub fn parse_sse_stream(raw: &[u8]) -> Result<Vec<GenerateContentResponse>, GoogleError>;
pub struct GoogleSseDecoder {
}
pub fn new() -> Self;
pub fn feed(&mut self, bytes: &[u8]) -> Result<(), GoogleError>;
pub fn drain(&mut self) -> Vec<GenerateContentResponse>;
pub fn finish(&mut self) -> Result<Vec<GenerateContentResponse>, GoogleError>;types.rs
Read declaration text · 18 declaration entries
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GenerateContentRequest {
/// The conversation contents (user and model turns).
pub contents: Vec<GeminiContent>,
/// System-level instructions, sent outside the conversation turns.
#[serde(skip_serializing_if = "Option::is_none")]
pub system_instruction: Option<GeminiContent>,
/// Tool configurations (function declarations).
#[serde(skip_serializing_if = "Option::is_none")]
pub tools: Option<Vec<GeminiToolConfig>>,
/// Generation parameters (temperature, max tokens, etc.).
#[serde(skip_serializing_if = "Option::is_none")]
pub generation_config: Option<GenerationConfig>
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GeminiContent {
/// The role of this content block: `"user"` or `"model"`.
/// System instructions may omit the role.
#[serde(skip_serializing_if = "Option::is_none")]
pub role: Option<String>,
/// The content parts (text, function calls, function responses, images).
pub parts: Vec<GeminiPart>
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GeminiPart {
/// A text part: `{"text": "..."}`.
Text {
/// The text content.
text: String,
},
/// A function call emitted by the model: `{"functionCall": {...}}`.
FunctionCall {
/// The function call details.
#[serde(rename = "functionCall")]
function_call: FnCall,
},
/// A function response provided by the client: `{"functionResponse": {...}}`.
FunctionResponse {
/// The function response details.
#[serde(rename = "functionResponse")]
function_response: FnResponse,
},
/// Inline binary data (images, etc.): `{"inlineData": {...}}`.
InlineData {
/// The binary data with MIME type.
#[serde(rename = "inlineData")]
inline_data: Blob,
},
}
pub fn text(text: impl Into<String>) -> Self;
pub fn function_call(name: impl Into<String>, args: serde_json::Value) -> Self;
pub fn function_response(name: impl Into<String>, response: serde_json::Value) -> Self;
pub fn inline_data(mime_type: impl Into<String>, data: impl Into<String>) -> Self;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FnCall {
/// The function name to invoke.
pub name: String,
/// The arguments as a JSON object.
pub args: serde_json::Value
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FnResponse {
/// The function name this response corresponds to.
pub name: String,
/// The function output as a JSON value.
pub response: serde_json::Value
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Blob {
/// The MIME type (e.g., `"image/png"`, `"image/jpeg"`).
pub mime_type: String,
/// Base64-encoded binary data.
pub data: String
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GeminiToolConfig {
/// The function declarations available to the model.
pub function_declarations: Vec<FunctionDeclaration>
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FunctionDeclaration {
/// The function name.
pub name: String,
/// A description of what the function does.
pub description: String,
/// The parameter schema as a JSON Schema object.
pub parameters: serde_json::Value
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GenerationConfig {
/// Sampling temperature (0.0 to 2.0).
#[serde(skip_serializing_if = "Option::is_none")]
pub temperature: Option<f64>,
/// Maximum number of tokens to generate.
#[serde(skip_serializing_if = "Option::is_none")]
pub max_output_tokens: Option<u32>,
/// Top-p (nucleus) sampling threshold.
#[serde(skip_serializing_if = "Option::is_none")]
pub top_p: Option<f64>,
/// Stop sequences -- generation stops when any of these appear.
#[serde(skip_serializing_if = "Option::is_none")]
pub stop_sequences: Option<Vec<String>>
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GenerateContentResponse {
/// The generated candidates (typically one).
#[serde(default)]
pub candidates: Vec<Candidate>,
/// Token usage metadata.
#[serde(skip_serializing_if = "Option::is_none")]
pub usage_metadata: Option<UsageMetadata>
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Candidate {
/// The generated content.
pub content: GeminiContent,
/// The reason generation stopped for this candidate.
#[serde(skip_serializing_if = "Option::is_none")]
pub finish_reason: Option<String>
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UsageMetadata {
/// Number of tokens in the input prompt.
#[serde(default)]
pub prompt_token_count: u64,
/// Number of tokens in the generated candidates.
#[serde(default)]
pub candidates_token_count: u64,
/// Total token count (prompt + candidates).
#[serde(default)]
pub total_token_count: u64
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GoogleApiErrorResponse {
/// The error details.
pub error: GoogleApiErrorDetail
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GoogleApiErrorDetail {
/// HTTP status code.
pub code: u16,
/// Error message.
pub message: String,
/// Error status string (e.g., "INVALID_ARGUMENT").
#[serde(default)]
pub status: String
}