llm/providers/openrouter/
types.rs1use async_openai::types::chat::{
2 ChatCompletionStreamOptions, ChatCompletionToolChoiceOption, ChatCompletionTools, ResponseFormat, StopConfiguration,
3};
4use serde::{Deserialize, Serialize};
5
6use crate::providers::openai_compatible::CompatibleChatRequest;
7use crate::providers::openai_compatible::types::CompatibleChatMessage;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct OpenRouterUsage {
12 #[serde(rename = "include")]
13 pub include: bool,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct CacheControl {
21 #[serde(rename = "type")]
22 pub cache_type: String,
23}
24
25impl CacheControl {
26 pub fn ephemeral() -> Self {
27 Self { cache_type: "ephemeral".to_string() }
28 }
29}
30
31#[derive(Debug, Clone, Serialize)]
36pub struct OpenRouterChatRequest {
37 pub model: String,
38 pub messages: Vec<CompatibleChatMessage>,
39 #[serde(skip_serializing_if = "Option::is_none")]
40 pub stream: Option<bool>,
41 #[serde(skip_serializing_if = "Option::is_none")]
42 pub tools: Option<Vec<ChatCompletionTools>>,
43 #[serde(skip_serializing_if = "Option::is_none")]
44 pub tool_choice: Option<ChatCompletionToolChoiceOption>,
45 #[serde(skip_serializing_if = "Option::is_none")]
46 pub temperature: Option<f32>,
47 #[serde(skip_serializing_if = "Option::is_none")]
48 pub top_p: Option<f32>,
49 #[serde(skip_serializing_if = "Option::is_none")]
50 pub max_completion_tokens: Option<u32>,
51 #[serde(skip_serializing_if = "Option::is_none")]
52 pub stream_options: Option<ChatCompletionStreamOptions>,
53 #[serde(skip_serializing_if = "Option::is_none")]
54 pub usage: Option<OpenRouterUsage>,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 pub presence_penalty: Option<f32>,
57 #[serde(skip_serializing_if = "Option::is_none")]
58 pub frequency_penalty: Option<f32>,
59 #[serde(skip_serializing_if = "Option::is_none")]
60 pub stop: Option<StopConfiguration>,
61 #[serde(skip_serializing_if = "Option::is_none")]
62 pub response_format: Option<ResponseFormat>,
63 #[serde(skip_serializing_if = "Option::is_none")]
64 pub reasoning_effort: Option<crate::ReasoningEffort>,
65 #[serde(skip_serializing_if = "Option::is_none")]
66 pub cache_control: Option<CacheControl>,
67}
68
69impl From<CompatibleChatRequest> for OpenRouterChatRequest {
70 fn from(request: CompatibleChatRequest) -> Self {
71 Self {
72 model: request.model,
73 messages: request.messages,
74 stream: request.stream,
75 tools: request.tools,
76 tool_choice: None,
77 temperature: None,
78 top_p: None,
79 max_completion_tokens: None,
80 stream_options: Some(ChatCompletionStreamOptions { include_usage: Some(true), include_obfuscation: None }),
81 usage: Some(OpenRouterUsage { include: true }),
82 presence_penalty: None,
83 frequency_penalty: None,
84 stop: None,
85 response_format: None,
86 reasoning_effort: None,
87 cache_control: Some(CacheControl::ephemeral()),
88 }
89 }
90}