openrouter_rs/
command.rs

1use futures_util::stream::BoxStream;
2use once_cell::sync::Lazy;
3use tokio::sync::Mutex;
4
5use crate::{
6    api::{api_keys, chat, completion, credits, generation, models},
7    config,
8    error::OpenRouterError,
9};
10
11// Lazy static variables to cache the API key and config
12static DEFAULT_API_KEY: Lazy<Mutex<Option<String>>> = Lazy::new(|| Mutex::new(None));
13static PROVISIONING_API_KEY: Lazy<Mutex<Option<String>>> = Lazy::new(|| Mutex::new(None));
14static CONFIG: Lazy<Mutex<Option<config::OpenRouterConfig>>> = Lazy::new(|| Mutex::new(None));
15
16async fn get_default_api_key() -> Result<String, OpenRouterError> {
17    let mut api_key = DEFAULT_API_KEY.lock().await;
18    if api_key.is_none() {
19        *api_key = Some(config::api_key::get()?.to_string());
20    }
21    Ok(api_key.clone().unwrap())
22}
23
24async fn get_provisioning_api_key() -> Result<String, OpenRouterError> {
25    let mut api_key = PROVISIONING_API_KEY.lock().await;
26    if api_key.is_none() {
27        *api_key = Some(config::api_key::get()?.to_string());
28    }
29    Ok(api_key.clone().unwrap())
30}
31
32async fn get_config() -> Result<config::OpenRouterConfig, OpenRouterError> {
33    let mut config = CONFIG.lock().await;
34    if config.is_none() {
35        *config = Some(config::load_config()?);
36    }
37    Ok(config.clone().unwrap())
38}
39
40/// Sets the API key for the OpenRouter client.
41///
42/// # Arguments
43///
44/// * `api_key` - The API key to set.
45///
46/// # Returns
47///
48/// * `Result<(), OpenRouterError>` - An empty result indicating success or an error.
49///
50/// # Example
51///
52/// ```
53/// set_api_key("your_api_key").await?;
54/// ```
55pub async fn set_api_key(api_key: &str) -> Result<(), OpenRouterError> {
56    config::api_key::store(api_key)?;
57    let mut cached_api_key = DEFAULT_API_KEY.lock().await;
58    *cached_api_key = Some(api_key.to_string());
59    Ok(())
60}
61
62/// Sends a chat completion request.
63///
64/// # Arguments
65///
66/// * `request` - The chat completion request.
67///
68/// # Returns
69///
70/// * `Result<chat::ChatCompletionResponse, OpenRouterError>` - The response from the chat completion request.
71///
72/// # Example
73///
74/// ```
75/// let request = chat::ChatCompletionRequest::builder()
76///     .model("deepseek/deepseek-chat:free")
77///     .messages(vec![chat::Message::new(chat::Role::User, "What is the meaning of life?")])
78///     .max_tokens(100)
79///     .temperature(0.7)
80///     .build()?;
81/// let response = send_chat_completion(request).await?;
82/// println!("{:?}", response);
83/// ```
84pub async fn send_chat_completion(
85    request: chat::ChatCompletionRequest,
86) -> Result<chat::ChatCompletionResponse, OpenRouterError> {
87    let config = get_config().await?;
88    let api_key = get_default_api_key().await?;
89    chat::send_chat_completion(&config.base_url, &api_key, &request).await
90}
91
92/// Streams chat completion events.
93///
94/// # Arguments
95///
96/// * `request` - The chat completion request.
97///
98/// # Returns
99///
100/// * `Result<BoxStream<'static, Result<chat::ChatCompletionStreamEvent, OpenRouterError>>, OpenRouterError>` - A stream of chat completion events or an error.
101///
102/// # Example
103///
104/// ```
105/// let request = chat::ChatCompletionRequest::builder()
106///     .model("deepseek/deepseek-chat:free")
107///     .messages(vec![chat::Message::new(chat::Role::User, "Tell me a joke.")])
108///     .max_tokens(50)
109///     .temperature(0.5)
110///     .build()?;
111/// let mut stream = stream_chat_completion(request).await?;
112/// while let Some(event) = stream.next().await {
113///     match event {
114///         Ok(event) => println!("{:?}", event),
115///         Err(e) => eprintln!("Error: {:?}", e),
116///     }
117/// }
118/// ```
119pub async fn stream_chat_completion(
120    request: chat::ChatCompletionRequest,
121) -> Result<
122    BoxStream<'static, Result<chat::ChatCompletionStreamEvent, OpenRouterError>>,
123    OpenRouterError,
124> {
125    let config = get_config().await?;
126    let api_key = get_default_api_key().await?;
127    chat::stream_chat_completion(&config.base_url, &api_key, &request).await
128}
129
130/// Sends a completion request.
131///
132/// # Arguments
133///
134/// * `request` - The completion request.
135///
136/// # Returns
137///
138/// * `Result<completion::CompletionResponse, OpenRouterError>` - The response from the completion request.
139///
140/// # Example
141///
142/// ```
143/// let request = completion::CompletionRequest::builder()
144///     .model("deepseek/deepseek-chat:free")
145///     .prompt("Once upon a time")
146///     .max_tokens(100)
147///     .temperature(0.7)
148///     .build()?;
149/// let response = send_completion(request).await?;
150/// println!("{:?}", response);
151/// ```
152pub async fn send_completion(
153    request: completion::CompletionRequest,
154) -> Result<completion::CompletionResponse, OpenRouterError> {
155    let config = get_config().await?;
156    let api_key = get_default_api_key().await?;
157    completion::send_completion_request(&config.base_url, &api_key, &request).await
158}
159
160/// Retrieves the total credits purchased and used for the authenticated user.
161///
162/// # Returns
163///
164/// * `Result<credits::CreditsData, OpenRouterError>` - The response data containing the total credits and usage.
165///
166/// # Example
167///
168/// ```
169/// let credits_data = get_credits().await?;
170/// println!("{:?}", credits_data);
171/// ```
172pub async fn get_credits() -> Result<credits::CreditsData, OpenRouterError> {
173    let config = get_config().await?;
174    let api_key = get_default_api_key().await?;
175    credits::get_credits(&config.base_url, &api_key).await
176}
177
178/// Retrieves metadata about a specific generation request.
179///
180/// # Arguments
181///
182/// * `generation_id` - The ID of the generation request.
183///
184/// # Returns
185///
186/// * `Result<generation::GenerationData, OpenRouterError>` - The metadata of the generation request or an error.
187///
188/// # Example
189///
190/// ```
191/// let generation_data = get_generation("generation_id").await?;
192/// println!("{:?}", generation_data);
193/// ```
194pub async fn get_generation(
195    generation_id: &str,
196) -> Result<generation::GenerationData, OpenRouterError> {
197    let config = get_config().await?;
198    let api_key = get_default_api_key().await?;
199    generation::get_generation(&config.base_url, &api_key, generation_id).await
200}
201
202/// Returns a list of models available through the API.
203///
204/// # Returns
205///
206/// * `Result<Vec<models::Model>, OpenRouterError>` - A list of models or an error.
207///
208/// # Example
209///
210/// ```
211/// let models = list_models().await?;
212/// println!("{:?}", models);
213/// ```
214pub async fn list_models() -> Result<Vec<models::Model>, OpenRouterError> {
215    let config = get_config().await?;
216    let api_key = get_default_api_key().await?;
217    models::list_models(&config.base_url, &api_key).await
218}
219
220/// Returns details about the endpoints for a specific model.
221///
222/// # Arguments
223///
224/// * `author` - The author of the model.
225/// * `slug` - The slug identifier for the model.
226///
227/// # Returns
228///
229/// * `Result<models::EndpointData, OpenRouterError>` - The endpoint data or an error.
230///
231/// # Example
232///
233/// ```
234/// let endpoint_data = list_model_endpoints("author_name", "model_slug").await?;
235/// println!("{:?}", endpoint_data);
236/// ```
237pub async fn list_model_endpoints(
238    author: &str,
239    slug: &str,
240) -> Result<models::EndpointData, OpenRouterError> {
241    let config = get_config().await?;
242    let api_key = get_default_api_key().await?;
243    models::list_model_endpoints(&config.base_url, &api_key, author, slug).await
244}
245
246/// Checks if a specific model is enabled.
247///
248/// # Arguments
249///
250/// * `model_id` - The ID of the model.
251///
252/// # Returns
253///
254/// * `Result<bool, OpenRouterError>` - A boolean indicating whether the model is enabled.
255///
256/// # Example
257///
258/// ```
259/// let is_enabled = is_model_enabled("model_id").await?;
260/// println!("Model enabled: {}", is_enabled);
261/// ```
262pub async fn is_model_enabled(model_id: &str) -> Result<bool, OpenRouterError> {
263    let config = get_config().await?;
264    Ok(config.models.is_enabled(model_id))
265}
266
267/// Retrieves information on the API key associated with the current authentication session.
268///
269/// # Returns
270///
271/// * `Result<api_keys::ApiKeyDetails, OpenRouterError>` - The details of the current API key.
272///
273/// # Example
274///
275/// ```
276/// let api_key_details = get_current_api_key().await?;
277/// println!("{:?}", api_key_details);
278/// ```
279pub async fn get_current_api_key() -> Result<api_keys::ApiKeyDetails, OpenRouterError> {
280    let config = get_config().await?;
281    let api_key = get_default_api_key().await?;
282    api_keys::get_current_api_key(&config.base_url, &api_key).await
283}
284
285/// Returns a list of all API keys associated with the account. Requires a Provisioning API key.
286///
287/// # Arguments
288///
289/// * `offset` - Optional offset for the API keys.
290/// * `include_disabled` - Optional flag to include disabled API keys.
291///
292/// # Returns
293///
294/// * `Result<Vec<api_keys::ApiKey>, OpenRouterError>` - A list of API keys.
295///
296/// # Example
297///
298/// ```
299/// let api_keys = list_api_keys(Some(0.0), Some(true)).await?;
300/// println!("{:?}", api_keys);
301/// ```
302pub async fn list_api_keys(
303    offset: Option<f64>,
304    include_disabled: Option<bool>,
305) -> Result<Vec<api_keys::ApiKey>, OpenRouterError> {
306    let config = get_config().await?;
307    let api_key = get_provisioning_api_key().await?;
308    api_keys::list_api_keys(&config.base_url, &api_key, offset, include_disabled).await
309}
310
311/// Creates a new API key. Requires a Provisioning API key.
312///
313/// # Arguments
314///
315/// * `name` - The display name for the new API key.
316/// * `limit` - Optional credit limit for the new API key.
317///
318/// # Returns
319///
320/// * `Result<api_keys::ApiKey, OpenRouterError>` - The created API key.
321///
322/// # Example
323///
324/// ```
325/// let api_key = create_api_key("New API Key", Some(100.0)).await?;
326/// println!("{:?}", api_key);
327/// ```
328pub async fn create_api_key(
329    name: &str,
330    limit: Option<f64>,
331) -> Result<api_keys::ApiKey, OpenRouterError> {
332    let config = get_config().await?;
333    let api_key = get_provisioning_api_key().await?;
334    api_keys::create_api_key(&config.base_url, &api_key, name, limit).await
335}
336
337/// Returns details about a specific API key. Requires a Provisioning API key.
338///
339/// # Arguments
340///
341/// * `hash` - The hash of the API key to retrieve.
342///
343/// # Returns
344///
345/// * `Result<api_keys::ApiKey, OpenRouterError>` - The details of the specified API key.
346///
347/// # Example
348///
349/// ```
350/// let api_key = get_api_key("api_key_hash").await?;
351/// println!("{:?}", api_key);
352/// ```
353pub async fn get_api_key(hash: &str) -> Result<api_keys::ApiKey, OpenRouterError> {
354    let config = get_config().await?;
355    let api_key = get_provisioning_api_key().await?;
356    api_keys::get_api_key(&config.base_url, &api_key, hash).await
357}
358
359/// Deletes an API key. Requires a Provisioning API key.
360///
361/// # Arguments
362///
363/// * `hash` - The hash of the API key to delete.
364///
365/// # Returns
366///
367/// * `Result<bool, OpenRouterError>` - A boolean indicating whether the deletion was successful.
368///
369/// # Example
370///
371/// ```
372/// let success = delete_api_key("api_key_hash").await?;
373/// println!("Deletion successful: {}", success);
374/// ```
375pub async fn delete_api_key(hash: &str) -> Result<bool, OpenRouterError> {
376    let config = get_config().await?;
377    let api_key = get_provisioning_api_key().await?;
378    api_keys::delete_api_key(&config.base_url, &api_key, hash).await
379}
380
381/// Updates an existing API key. Requires a Provisioning API key.
382///
383/// # Arguments
384///
385/// * `hash` - The hash of the API key to update.
386/// * `name` - Optional new display name for the API key.
387/// * `disabled` - Optional flag to disable the API key.
388/// * `limit` - Optional new credit limit for the API key.
389///
390/// # Returns
391///
392/// * `Result<api_keys::ApiKey, OpenRouterError>` - The updated API key.
393///
394/// # Example
395///
396/// ```
397/// let updated_api_key = update_api_key("api_key_hash", Some("Updated Name".to_string()), Some(false), Some(200.0)).await?;
398/// println!("{:?}", updated_api_key);
399/// ```
400pub async fn update_api_key(
401    hash: &str,
402    name: Option<String>,
403    disabled: Option<bool>,
404    limit: Option<f64>,
405) -> Result<api_keys::ApiKey, OpenRouterError> {
406    let config = get_config().await?;
407    let api_key = get_provisioning_api_key().await?;
408    api_keys::update_api_key(&config.base_url, &api_key, hash, name, disabled, limit).await
409}