use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum Role {
User,
Assistant,
System,
Tool,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ContentBlock {
#[serde(alias = "Text")]
Text { text: String },
#[serde(alias = "ToolUse")]
ToolUse {
id: String,
name: String,
input: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none", default)]
provider_metadata: Option<serde_json::Value>,
},
#[serde(alias = "ToolResult")]
ToolResult {
tool_use_id: String,
content: String,
is_error: bool,
},
#[serde(alias = "Thinking")]
Thinking {
thinking: String,
#[serde(skip_serializing_if = "Option::is_none", default)]
signature: Option<String>,
},
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ConversationMessage {
pub role: Role,
pub content: Vec<ContentBlock>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum StopReason {
EndTurn,
ToolUse,
MaxTokens,
Unknown(String),
}
impl StopReason {
pub fn as_str(&self) -> &str {
match self {
StopReason::EndTurn => "end_turn",
StopReason::ToolUse => "tool_use",
StopReason::MaxTokens => "max_tokens",
StopReason::Unknown(s) => s.as_str(),
}
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
pub struct UsageStats {
pub input_tokens: u32,
pub output_tokens: u32,
pub total_tokens: u32,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub thinking_tokens: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cache_read_tokens: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cache_creation_tokens: Option<u32>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ModelResponse {
pub content: Vec<ContentBlock>,
pub stop_reason: StopReason,
pub usage: Option<UsageStats>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub thinking: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
pub struct InferenceConfig {
pub model: Option<String>,
pub max_tokens: Option<u32>,
pub temperature: Option<f32>,
pub top_p: Option<f32>,
pub stop_sequences: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub response_format: Option<ResponseFormat>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ResponseFormat {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
pub schema: serde_json::Value,
}
impl ResponseFormat {
pub fn new(schema: serde_json::Value) -> Self {
Self { name: None, schema }
}
pub fn named(name: impl Into<String>, schema: serde_json::Value) -> Self {
Self {
name: Some(name.into()),
schema,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ToolDefinition {
pub name: String,
pub description: String,
pub parameters: serde_json::Value,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum StreamEvent {
ContentDelta {
text: String,
},
ToolUseDelta {
id: String,
name: Option<String>,
input_delta: Option<String>,
provider_metadata: Option<serde_json::Value>,
#[serde(default)]
index: Option<u32>,
},
StopEvent {
stop_reason: StopReason,
},
ThinkingDelta {
text: String,
},
UsageEvent {
input_tokens: u32,
output_tokens: u32,
#[serde(default)]
thinking_tokens: Option<u32>,
#[serde(default)]
cache_read_tokens: Option<u32>,
#[serde(default)]
cache_creation_tokens: Option<u32>,
},
ThinkingBlock {
thinking: String,
#[serde(default)]
signature: Option<String>,
},
Error {
message: String,
},
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ToolResult {
pub content: String,
pub is_error: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ModelInfo {
pub id: String,
pub object: String,
pub created: u64,
pub owned_by: String,
}