use std::pin::Pin;
use futures_util::Stream;
use serde::{Deserialize, Serialize};
use crate::message::{Message, Reasoning, ToolCall};
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct CompletionRequest {
pub preamble: Option<String>,
pub chat_history: Vec<Message>,
pub tools: Vec<ToolDefinition>,
pub max_tokens: Option<u64>,
pub additional_params: Option<serde_json::Value>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct ToolDefinition {
pub name: String,
pub description: String,
pub parameters: serde_json::Value,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct Usage {
#[serde(default)]
pub input_tokens: u64,
#[serde(default)]
pub output_tokens: u64,
#[serde(default)]
pub total_tokens: u64,
#[serde(default)]
pub cached_input_tokens: u64,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum ErrorClass {
Transient,
Throttled,
ContextOverflow,
Fatal,
}
#[derive(Debug, thiserror::Error)]
pub enum CompletionError {
#[error("RequestError: {0}")]
RequestError(#[from] Box<dyn std::error::Error + Send + Sync + 'static>),
#[error("ResponseError: {0}")]
ResponseError(String),
#[error("ProviderError: {message}")]
ProviderError { message: String, class: ErrorClass },
#[error("JsonError: {0}")]
JsonError(#[from] serde_json::Error),
}
impl CompletionError {
pub fn provider(class: ErrorClass, message: impl Into<String>) -> Self {
Self::ProviderError {
message: message.into(),
class,
}
}
pub fn class(&self) -> ErrorClass {
match self {
Self::RequestError(_) | Self::JsonError(_) => ErrorClass::Fatal,
Self::ResponseError(_) => ErrorClass::Transient,
Self::ProviderError { class, .. } => *class,
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum StreamChunk {
Text(String),
ToolCall(ToolCall),
ToolCallDelta {
id: String,
content: ToolCallDeltaContent,
},
Reasoning(Reasoning),
ReasoningDelta { id: Option<String>, text: String },
Final(FinalResponse),
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum ToolCallDeltaContent {
Name(String),
Delta(String),
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct FinalResponse {
pub usage: Option<Usage>,
}
pub type ModelStream = Pin<Box<dyn Stream<Item = Result<StreamChunk, CompletionError>> + Send>>;