use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct AnthropicRequest {
pub model: String,
pub messages: Vec<Message>,
pub max_tokens: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub thinking: Option<ThinkingConfig>,
#[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 top_k: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub stop_sequences: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub stream: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<HashMap<String, serde_json::Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub system: Option<SystemPrompt>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tools: Option<Vec<Tool>>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Message {
pub role: String,
pub content: MessageContent,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum MessageContent {
Text(String),
Blocks(Vec<ContentBlock>),
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum SystemPrompt {
Text(String),
Blocks(Vec<SystemBlock>),
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct SystemBlock {
pub r#type: String,
pub text: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub cache_control: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum ToolResultContent {
Text(String),
Blocks(Vec<ToolResultBlock>),
}
impl ToolResultContent {
pub fn to_string(&self) -> String {
match self {
ToolResultContent::Text(s) => s.clone(),
ToolResultContent::Blocks(blocks) => {
blocks.iter()
.filter_map(|block| match block {
ToolResultBlock::Text { text } => Some(text.clone()),
ToolResultBlock::Image { .. } => Some("[Image]".to_string()),
})
.collect::<Vec<_>>()
.join("\n")
}
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(tag = "type")]
pub enum ToolResultBlock {
#[serde(rename = "text")]
Text { text: String },
#[serde(rename = "image")]
Image { source: ImageSource },
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(tag = "type")]
pub enum ContentBlock {
#[serde(rename = "text")]
Text { text: String },
#[serde(rename = "image")]
Image {
source: ImageSource,
},
#[serde(rename = "tool_use")]
ToolUse {
id: String,
name: String,
input: serde_json::Value,
},
#[serde(rename = "tool_result")]
ToolResult {
tool_use_id: String,
content: ToolResultContent,
},
#[serde(rename = "thinking")]
Thinking {
thinking: String,
signature: String,
},
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ImageSource {
pub r#type: String, #[serde(skip_serializing_if = "Option::is_none")]
pub media_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Tool {
#[serde(skip_serializing_if = "Option::is_none")]
pub r#type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub input_schema: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ThinkingConfig {
pub r#type: String, #[serde(skip_serializing_if = "Option::is_none")]
pub budget_tokens: Option<u32>,
}
#[allow(dead_code)]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Usage {
pub input_tokens: u32,
pub output_tokens: u32,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct CountTokensRequest {
pub model: String,
pub messages: Vec<Message>,
#[serde(skip_serializing_if = "Option::is_none")]
pub system: Option<SystemPrompt>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tools: Option<Vec<Tool>>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct CountTokensResponse {
pub input_tokens: u32,
}
#[derive(Debug, Clone)]
pub struct RouteDecision {
pub model_name: String,
pub route_type: RouteType,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RouteType {
WebSearch,
Think,
Background,
Default,
}
impl std::fmt::Display for RouteType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
RouteType::WebSearch => write!(f, "web-search"),
RouteType::Think => write!(f, "think"),
RouteType::Background => write!(f, "background"),
RouteType::Default => write!(f, "default"),
}
}
}