use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum Role {
System,
Developer,
User,
Assistant,
Tool,
Function,
Other(String),
}
impl Serialize for Role {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
Self::System => serializer.serialize_str("system"),
Self::Developer => serializer.serialize_str("developer"),
Self::User => serializer.serialize_str("user"),
Self::Assistant => serializer.serialize_str("assistant"),
Self::Tool => serializer.serialize_str("tool"),
Self::Function => serializer.serialize_str("function"),
Self::Other(s) => serializer.serialize_str(s),
}
}
}
impl<'de> Deserialize<'de> for Role {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let s = String::deserialize(deserializer)?;
match s.as_str() {
"system" => Ok(Self::System),
"developer" => Ok(Self::Developer),
"user" => Ok(Self::User),
"assistant" => Ok(Self::Assistant),
"tool" => Ok(Self::Tool),
"function" => Ok(Self::Function),
_ => Ok(Self::Other(s)),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum FinishReason {
Stop,
Length,
ToolCalls,
ContentFilter,
FunctionCall,
Other(String),
}
impl Serialize for FinishReason {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
Self::Stop => serializer.serialize_str("stop"),
Self::Length => serializer.serialize_str("length"),
Self::ToolCalls => serializer.serialize_str("tool_calls"),
Self::ContentFilter => serializer.serialize_str("content_filter"),
Self::FunctionCall => serializer.serialize_str("function_call"),
Self::Other(s) => serializer.serialize_str(s),
}
}
}
impl<'de> Deserialize<'de> for FinishReason {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let s = String::deserialize(deserializer)?;
match s.as_str() {
"stop" => Ok(Self::Stop),
"length" => Ok(Self::Length),
"tool_calls" => Ok(Self::ToolCalls),
"content_filter" => Ok(Self::ContentFilter),
"function_call" => Ok(Self::FunctionCall),
_ => Ok(Self::Other(s)),
}
}
}
impl std::fmt::Display for FinishReason {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Stop => write!(f, "stop"),
Self::Length => write!(f, "length"),
Self::ToolCalls => write!(f, "tool_calls"),
Self::ContentFilter => write!(f, "content_filter"),
Self::FunctionCall => write!(f, "function_call"),
Self::Other(s) => write!(f, "{s}"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum ServiceTier {
Auto,
Default,
Flex,
Scale,
Priority,
Other(String),
}
impl Serialize for ServiceTier {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
Self::Auto => serializer.serialize_str("auto"),
Self::Default => serializer.serialize_str("default"),
Self::Flex => serializer.serialize_str("flex"),
Self::Scale => serializer.serialize_str("scale"),
Self::Priority => serializer.serialize_str("priority"),
Self::Other(s) => serializer.serialize_str(s),
}
}
}
impl<'de> Deserialize<'de> for ServiceTier {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let s = String::deserialize(deserializer)?;
match s.as_str() {
"auto" => Ok(Self::Auto),
"default" => Ok(Self::Default),
"flex" => Ok(Self::Flex),
"scale" => Ok(Self::Scale),
"priority" => Ok(Self::Priority),
_ => Ok(Self::Other(s)),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum SearchContextSize {
Low,
Medium,
High,
Other(String),
}
impl Serialize for SearchContextSize {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
Self::Low => serializer.serialize_str("low"),
Self::Medium => serializer.serialize_str("medium"),
Self::High => serializer.serialize_str("high"),
Self::Other(s) => serializer.serialize_str(s),
}
}
}
impl<'de> Deserialize<'de> for SearchContextSize {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let s = String::deserialize(deserializer)?;
match s.as_str() {
"low" => Ok(Self::Low),
"medium" => Ok(Self::Medium),
"high" => Ok(Self::High),
_ => Ok(Self::Other(s)),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum SortOrder {
Asc,
Desc,
Other(String),
}
impl Serialize for SortOrder {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
Self::Asc => serializer.serialize_str("asc"),
Self::Desc => serializer.serialize_str("desc"),
Self::Other(s) => serializer.serialize_str(s),
}
}
}
impl<'de> Deserialize<'de> for SortOrder {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let s = String::deserialize(deserializer)?;
match s.as_str() {
"asc" => Ok(Self::Asc),
"desc" => Ok(Self::Desc),
_ => Ok(Self::Other(s)),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "structured", derive(schemars::JsonSchema))]
pub struct Usage {
#[serde(default)]
pub prompt_tokens: Option<i64>,
#[serde(default)]
pub completion_tokens: Option<i64>,
#[serde(default)]
pub total_tokens: Option<i64>,
#[serde(default)]
pub prompt_tokens_details: Option<PromptTokensDetails>,
#[serde(default)]
pub completion_tokens_details: Option<CompletionTokensDetails>,
}
impl Usage {
pub fn cached_tokens(&self) -> i64 {
self.prompt_tokens_details
.as_ref()
.and_then(|d| d.cached_tokens)
.unwrap_or(0)
}
pub fn cache_hit_pct(&self) -> u64 {
let input = self.prompt_tokens.unwrap_or(0) as u64;
let cached = self.cached_tokens() as u64;
if input > 0 { (cached * 100) / input } else { 0 }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "structured", derive(schemars::JsonSchema))]
pub struct PromptTokensDetails {
#[serde(default)]
pub cached_tokens: Option<i64>,
#[serde(default)]
pub audio_tokens: Option<i64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "structured", derive(schemars::JsonSchema))]
pub struct CompletionTokensDetails {
#[serde(default)]
pub reasoning_tokens: Option<i64>,
#[serde(default)]
pub audio_tokens: Option<i64>,
#[serde(default)]
pub accepted_prediction_tokens: Option<i64>,
#[serde(default)]
pub rejected_prediction_tokens: Option<i64>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum AutoOrFixed<T> {
Auto,
Fixed(T),
}
impl<T: Serialize> Serialize for AutoOrFixed<T> {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
Self::Auto => serializer.serialize_str("auto"),
Self::Fixed(v) => v.serialize(serializer),
}
}
}
impl<'de, T: Deserialize<'de>> Deserialize<'de> for AutoOrFixed<T> {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let value = serde_json::Value::deserialize(deserializer)?;
match &value {
serde_json::Value::String(s) if s == "auto" => Ok(Self::Auto),
_ => T::deserialize(value)
.map(Self::Fixed)
.map_err(serde::de::Error::custom),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum MaxResponseTokens {
Inf,
Fixed(i64),
}
impl Serialize for MaxResponseTokens {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
Self::Inf => serializer.serialize_str("inf"),
Self::Fixed(v) => serializer.serialize_i64(*v),
}
}
}
impl<'de> Deserialize<'de> for MaxResponseTokens {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let value = serde_json::Value::deserialize(deserializer)?;
match &value {
serde_json::Value::String(s) if s == "inf" => Ok(Self::Inf),
serde_json::Value::Number(n) => n
.as_i64()
.map(Self::Fixed)
.ok_or_else(|| serde::de::Error::custom("expected integer")),
_ => Err(serde::de::Error::custom("expected \"inf\" or integer")),
}
}
}