use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ChatOptions {
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
#[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 = "Option::is_none")]
pub max_tokens: Option<u32>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub stop: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub frequency_penalty: Option<f32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub presence_penalty: Option<f32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChatResponse {
pub message: crate::Message,
pub usage: Option<Usage>,
pub finish_reason: String,
pub model: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Usage {
pub prompt_tokens: u32,
pub completion_tokens: u32,
pub total_tokens: u32,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct StreamChunk {
pub content: String,
pub is_delta: bool,
pub is_done: bool,
pub finish_reason: Option<String>,
pub usage: Option<Usage>,
#[serde(default)]
pub tool_calls_delta: Vec<ToolCallDelta>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ToolCallDelta {
pub index: u32,
pub id: Option<String>,
pub name: Option<String>,
pub arguments_delta: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum HealthStatus {
Healthy {
latency_ms: u64,
},
Degraded {
reason: String,
},
Unhealthy {
reason: String,
},
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Message;
#[test]
fn chat_options_default_minimal() {
let opts = ChatOptions::default();
let s = serde_json::to_string(&opts).unwrap();
assert_eq!(s, "{}");
}
#[test]
fn chat_response_roundtrip() {
let r = ChatResponse {
message: Message::ai("hello"),
usage: Some(Usage {
prompt_tokens: 10,
completion_tokens: 5,
total_tokens: 15,
}),
finish_reason: "stop".into(),
model: "gpt-4o".into(),
};
let s = serde_json::to_string(&r).unwrap();
let back: ChatResponse = serde_json::from_str(&s).unwrap();
assert_eq!(back.finish_reason, "stop");
assert_eq!(back.usage.unwrap().total_tokens, 15);
}
}