use crate::model::{Message, Role, tool::ToolCall};
pub use crabllm_core::{CompletionTokensDetails, FinishReason, Usage};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize, Default)]
pub struct CompletionMeta {
pub id: String,
pub object: String,
pub created: u64,
pub model: String,
pub system_fingerprint: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Default)]
pub struct Delta {
pub role: Option<Role>,
pub content: Option<String>,
pub reasoning_content: Option<String>,
pub tool_calls: Option<Vec<ToolCall>>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct Response {
#[serde(flatten)]
pub meta: CompletionMeta,
pub choices: Vec<Choice>,
pub usage: Usage,
}
impl Response {
pub fn message(&self) -> Option<Message> {
let choice = self.choices.first()?;
Some(Message::assistant(
choice.delta.content.clone().unwrap_or_default(),
choice.delta.reasoning_content.clone(),
choice.delta.tool_calls.as_deref(),
))
}
pub fn content(&self) -> Option<&String> {
self.choices
.first()
.and_then(|choice| choice.delta.content.as_ref())
}
pub fn reasoning(&self) -> Option<&String> {
self.choices
.first()
.and_then(|choice| choice.delta.reasoning_content.as_ref())
}
pub fn tool_calls(&self) -> Option<&[ToolCall]> {
self.choices
.first()
.and_then(|choice| choice.delta.tool_calls.as_deref())
}
pub fn reason(&self) -> Option<&FinishReason> {
self.choices
.first()
.and_then(|choice| choice.finish_reason.as_ref())
}
}
#[derive(Debug, Clone, Deserialize, Default)]
pub struct Choice {
pub index: u32,
#[serde(alias = "message")]
pub delta: Delta,
pub finish_reason: Option<FinishReason>,
pub logprobs: Option<LogProbs>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct LogProbs {
pub content: Option<Vec<LogProb>>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct LogProb {
pub token: String,
pub logprob: f64,
#[serde(skip_serializing_if = "Option::is_none")]
pub bytes: Option<Vec<u8>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub top_logprobs: Option<Vec<TopLogProb>>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct TopLogProb {
pub token: String,
pub logprob: f64,
#[serde(skip_serializing_if = "Option::is_none")]
pub bytes: Option<Vec<u8>>,
}