Skip to main content

openrouter_rust/
generations.rs

1use crate::{
2    client::OpenRouterClient,
3    error::{OpenRouterError, Result},
4};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct GenerationResponse {
9    pub data: GenerationData,
10}
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct GenerationData {
14    pub id: String,
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub upstream_id: Option<String>,
17    pub total_cost: f64,
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub cache_discount: Option<f64>,
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub upstream_inference_cost: Option<f64>,
22    pub created_at: String,
23    pub model: String,
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub app_id: Option<f64>,
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub streamed: Option<bool>,
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub cancelled: Option<bool>,
30    #[serde(skip_serializing_if = "Option::is_none")]
31    pub provider_name: Option<String>,
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub latency: Option<f64>,
34    #[serde(skip_serializing_if = "Option::is_none")]
35    pub moderation_latency: Option<f64>,
36    #[serde(skip_serializing_if = "Option::is_none")]
37    pub generation_time: Option<f64>,
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub finish_reason: Option<String>,
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub tokens_prompt: Option<f64>,
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub tokens_completion: Option<f64>,
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub native_tokens_prompt: Option<f64>,
46    #[serde(skip_serializing_if = "Option::is_none")]
47    pub native_tokens_completion: Option<f64>,
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub native_tokens_completion_images: Option<f64>,
50    #[serde(skip_serializing_if = "Option::is_none")]
51    pub native_tokens_reasoning: Option<f64>,
52    #[serde(skip_serializing_if = "Option::is_none")]
53    pub native_tokens_cached: Option<f64>,
54    #[serde(skip_serializing_if = "Option::is_none")]
55    pub num_media_prompt: Option<f64>,
56    #[serde(skip_serializing_if = "Option::is_none")]
57    pub num_input_audio_prompt: Option<f64>,
58    #[serde(skip_serializing_if = "Option::is_none")]
59    pub num_media_completion: Option<f64>,
60    #[serde(skip_serializing_if = "Option::is_none")]
61    pub num_search_results: Option<f64>,
62    pub origin: String,
63    pub usage: f64,
64    pub is_byok: bool,
65    #[serde(skip_serializing_if = "Option::is_none")]
66    pub native_finish_reason: Option<String>,
67    #[serde(skip_serializing_if = "Option::is_none")]
68    pub external_user: Option<String>,
69    #[serde(skip_serializing_if = "Option::is_none")]
70    pub api_type: Option<String>,
71    #[serde(skip_serializing_if = "Option::is_none")]
72    pub router: Option<String>,
73    #[serde(skip_serializing_if = "Option::is_none")]
74    pub provider_responses: Option<Vec<ProviderResponse>>,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct ProviderResponse {
79    pub id: String,
80    pub endpoint_id: String,
81    pub model_permaslug: String,
82    pub provider_name: String,
83    #[serde(skip_serializing_if = "Option::is_none")]
84    pub status: Option<f64>,
85    pub latency: f64,
86    pub is_byok: bool,
87}
88
89impl OpenRouterClient {
90    pub async fn get_generation(&self, generation_id: impl Into<String>) -> Result<GenerationResponse> {
91        let url = format!("{}/generation?id={}", self.base_url, generation_id.into());
92        let headers = self.build_headers()?;
93
94        let response = self
95            .client
96            .get(&url)
97            .headers(headers)
98            .send()
99            .await
100            .map_err(OpenRouterError::HttpError)?;
101
102        let status = response.status();
103        
104        if !status.is_success() {
105            let error_text = response.text().await.unwrap_or_default();
106            return Err(OpenRouterError::ApiError {
107                code: status.as_u16(),
108                message: error_text,
109            });
110        }
111
112        let result = response
113            .json::<GenerationResponse>()
114            .await
115            .map_err(OpenRouterError::HttpError)?;
116
117        Ok(result)
118    }
119}