use crate::chat_client::openai_api::message::{
RequestGenericMessage, ResponseGenericMessage, Role,
};
use serde::{Deserialize, Serialize};
use serde_json::value::Value;
use std::collections::HashMap;
#[derive(Debug, Default, Clone, PartialEq, Serialize)]
pub struct ChatCompletionsRequest {
pub messages: Vec<RequestGenericMessage>,
pub model: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub frequency_penalty: Option<f32>,
#[serde(skip_serializing_if = "HashMap::is_empty")]
pub logit_bias: HashMap<String, f32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub logprobs: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub top_logprobs: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_completion_tokens: Option<usize>,
#[serde(rename = "n")]
#[serde(skip_serializing_if = "Option::is_none")]
pub completion_choices: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub presence_penalty: Option<f32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub response_format: Option<Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub service_tier: Option<String>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub stop: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub stream: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub stream_options: Option<StreamOptions>,
#[serde(skip_serializing_if = "Option::is_none")]
pub temperature: Option<f32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub top_p: Option<f32>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub tools: Vec<Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tool_choice: Option<Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parallel_tool_calls: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub prompt_cache_key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub safety_identifier: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reasoning_effort: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub verbosity: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub web_search_options: Option<Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reasoning: Option<OpenRouterReasoning>,
#[serde(skip_serializing_if = "Option::is_none")]
pub plugins: Option<Vec<Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub modalities: Option<Value>,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
pub struct StreamOptions {
#[serde(skip_serializing_if = "Option::is_none")]
pub include_obfuscation: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub include_usage: Option<bool>,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
pub struct OpenRouterReasoning {
pub effort: Option<String>,
pub max_tokens: Option<i64>,
#[serde(skip_serializing_if = "std::ops::Not::not")]
pub exclude: bool,
}
impl OpenRouterReasoning {
pub fn from_effort(effort: String) -> Self {
Self {
effort: Some(effort),
max_tokens: None,
exclude: false,
}
}
pub fn from_budget(max_tokens: i64) -> Self {
Self {
effort: None,
max_tokens: Some(max_tokens),
exclude: false,
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, Deserialize)]
pub struct ChatCompletions {
pub id: String,
pub choices: Vec<CompletionChoice>,
pub created: u64,
pub model: String,
pub service_tier: Option<String>,
pub system_fingerprint: Option<String>,
pub object: String,
pub usage: Usage,
pub provider: Option<String>,
}
#[derive(Debug, Clone, Eq, PartialEq, Deserialize)]
pub struct CompletionChoice {
pub finish_reason: String,
pub index: usize,
pub message: ResponseGenericMessage,
pub logprobs: Option<Value>,
pub native_finish_reason: Option<String>,
}
#[derive(Debug, Clone, Eq, PartialEq, Deserialize)]
pub struct Usage {
pub prompt_tokens: usize,
pub completion_tokens: usize,
pub total_tokens: usize,
pub prompt_tokens_details: Option<PromptTokensDetails>,
pub completion_tokens_details: Option<CompletionTokensDetails>,
}
#[derive(Debug, Clone, Eq, PartialEq, Deserialize)]
pub struct PromptTokensDetails {
pub audio_tokens: Option<usize>,
pub cached_tokens: Option<usize>,
}
#[derive(Debug, Clone, Eq, PartialEq, Deserialize)]
pub struct CompletionTokensDetails {
pub accepted_prediction_tokens: Option<usize>,
pub audio_tokens: Option<usize>,
pub reasoning_tokens: Option<usize>,
pub rejected_prediction_tokens: Option<usize>,
}
#[derive(Debug, Clone, Eq, PartialEq, Deserialize)]
pub struct StreamingDelta {
pub content: Option<String>,
pub refusal: Option<String>,
pub role: Option<Role>,
pub tool_calls: Option<Vec<Value>>,
pub reasoning: Option<String>,
}
#[derive(Debug, Clone, Eq, PartialEq, Deserialize)]
pub struct StreamingChoice {
pub delta: StreamingDelta,
pub finish_reason: Option<String>,
pub index: usize,
pub logprobs: Option<Value>,
}
#[derive(Debug, Clone, Eq, PartialEq, Deserialize)]
pub struct StreamingChunk {
pub choices: Vec<StreamingChoice>,
pub created: u64,
pub id: String,
pub model: String,
pub object: String,
pub service_tier: Option<String>,
pub usage: Option<Usage>,
}