#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct UsageStats {
pub prompt_tokens: usize,
pub completion_tokens: usize,
pub total_tokens: usize,
pub cache_read_tokens: usize,
pub cache_creation_tokens: usize,
}
impl std::ops::AddAssign for UsageStats {
fn add_assign(&mut self, rhs: Self) {
self.prompt_tokens += rhs.prompt_tokens;
self.completion_tokens += rhs.completion_tokens;
self.total_tokens += rhs.total_tokens;
self.cache_read_tokens += rhs.cache_read_tokens;
self.cache_creation_tokens += rhs.cache_creation_tokens;
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum FinishReason {
#[default]
Stop,
Length,
ToolCalls,
ContentFilter,
Other(String),
}
impl FinishReason {
pub fn is_truncated(&self) -> bool {
matches!(self, FinishReason::Length)
}
}
impl From<&str> for FinishReason {
fn from(s: &str) -> Self {
match s {
"stop" | "STOP" => FinishReason::Stop,
"length" | "MAX_TOKENS" => FinishReason::Length,
"tool_calls" | "MALFORMED_FUNCTION_CALL" => FinishReason::ToolCalls,
"content_filter" | "SAFETY" | "PROHIBITED_CONTENT" | "SPII" | "BLOCKLIST" => FinishReason::ContentFilter,
"end_turn" => FinishReason::Stop,
"max_tokens" => FinishReason::Length,
"tool_use" => FinishReason::ToolCalls,
"stop_sequence" => FinishReason::Stop,
other => FinishReason::Other(other.to_string()),
}
}
}
#[derive(Debug, Clone, Default)]
pub struct CompleteResponse {
pub content: Option<String>,
pub reasoning: Option<String>,
pub tool_calls: Vec<crate::request::ToolCall>,
pub usage: UsageStats,
pub finish_reason: FinishReason,
}
impl CompleteResponse {
pub fn json<T: serde::de::DeserializeOwned>(&self) -> serde_json::Result<T> {
serde_json::from_str(self.content.as_deref().unwrap_or(""))
}
}
#[derive(Debug, Clone)]
pub struct ToolCallChunk {
pub id: String,
pub name: String,
pub delta: String,
pub index: u32,
}
#[derive(Debug)]
pub struct PartialToolCall {
pub id: String,
pub name: String,
pub arguments: String,
}
pub struct StreamBufs {
pub content_buf: String,
pub reasoning_buf: String,
pub tool_call_bufs: Vec<Option<PartialToolCall>>,
}
impl StreamBufs {
pub fn new() -> Self {
Self {
content_buf: String::new(),
reasoning_buf: String::new(),
tool_call_bufs: Vec::new(),
}
}
}
impl Default for StreamBufs {
fn default() -> Self {
Self::new()
}
}