openrouter_rs/api/
generation.rs1use std::collections::HashMap;
2
3use reqwest::Client as HttpClient;
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6
7use crate::{
8 error::OpenRouterError,
9 transport::{request as transport_request, response as transport_response},
10 types::ApiResponse,
11};
12
13#[derive(Serialize, Deserialize, Debug)]
14#[non_exhaustive]
15pub struct GenerationData {
16 pub id: String,
17 pub total_cost: f64,
18 pub created_at: String,
19 #[serde(default, skip_serializing_if = "Option::is_none")]
20 pub data_region: Option<String>,
21 pub model: String,
22 pub origin: String,
23 pub usage: f64,
24 pub is_byok: bool,
25 pub upstream_id: Option<String>,
26 pub cache_discount: Option<f64>,
27 pub app_id: Option<u32>,
28 pub streamed: Option<bool>,
29 pub cancelled: Option<bool>,
30 pub provider_name: Option<String>,
31 pub latency: Option<f64>,
32 pub moderation_latency: Option<u32>,
33 pub generation_time: Option<u32>,
34 pub finish_reason: Option<String>,
35 pub native_finish_reason: Option<String>,
36 pub tokens_prompt: Option<u32>,
37 pub tokens_completion: Option<u32>,
38 pub native_tokens_prompt: Option<u32>,
39 pub native_tokens_completion: Option<u32>,
40 pub native_tokens_reasoning: Option<u32>,
41 pub num_fetches: Option<u32>,
42 pub num_media_prompt: Option<u32>,
43 pub num_media_completion: Option<u32>,
44 pub num_search_results: Option<u32>,
45 pub preset_id: Option<String>,
46 pub response_cache_source_id: Option<String>,
47 pub service_tier: Option<String>,
48 #[serde(default, skip_serializing_if = "Option::is_none")]
49 pub status: Option<i32>,
50}
51
52#[derive(Serialize, Deserialize, Debug, Clone)]
54#[non_exhaustive]
55pub struct GenerationContentData {
56 #[serde(default)]
57 pub input: HashMap<String, Value>,
58 #[serde(default)]
59 pub output: HashMap<String, Value>,
60}
61
62pub async fn get_generation(
74 base_url: &str,
75 api_key: &str,
76 id: impl Into<String>,
77) -> Result<GenerationData, OpenRouterError> {
78 let http_client = crate::transport::new_client()?;
79 get_generation_with_client(&http_client, base_url, api_key, id).await
80}
81
82pub(crate) async fn get_generation_with_client(
83 http_client: &HttpClient,
84 base_url: &str,
85 api_key: &str,
86 id: impl Into<String>,
87) -> Result<GenerationData, OpenRouterError> {
88 let id = id.into();
89 let url = format!("{base_url}/generation?id={id}");
90
91 let response =
92 transport_request::with_bearer_auth(transport_request::get(http_client, &url), api_key)
93 .send()
94 .await?;
95
96 if response.status().is_success() {
97 let generation_response: ApiResponse<_> =
98 transport_response::parse_json_response(response, "generation").await?;
99 Ok(generation_response.data)
100 } else {
101 transport_response::handle_error(response).await?;
102 unreachable!()
103 }
104}
105
106pub async fn get_generation_content(
108 base_url: &str,
109 api_key: &str,
110 id: impl Into<String>,
111) -> Result<GenerationContentData, OpenRouterError> {
112 let http_client = crate::transport::new_client()?;
113 get_generation_content_with_client(&http_client, base_url, api_key, id).await
114}
115
116pub(crate) async fn get_generation_content_with_client(
117 http_client: &HttpClient,
118 base_url: &str,
119 api_key: &str,
120 id: impl Into<String>,
121) -> Result<GenerationContentData, OpenRouterError> {
122 let id = id.into();
123 let url = format!("{base_url}/generation/content?id={id}");
124
125 let response =
126 transport_request::with_bearer_auth(transport_request::get(http_client, &url), api_key)
127 .send()
128 .await?;
129
130 if response.status().is_success() {
131 let generation_response: ApiResponse<_> =
132 transport_response::parse_json_response(response, "generation content").await?;
133 Ok(generation_response.data)
134 } else {
135 transport_response::handle_error(response).await?;
136 unreachable!()
137 }
138}