use crate::core::tools::ToolDefinition;
use serde::{Deserialize, Serialize};
use std::env;
pub const ANTHROPIC_BASE_URL: &str = "https://api.anthropic.com/v1";
pub const CLAUDE_MODELS: [&str; 5] = [
"claude-3-5-sonnet-20241022", "claude-3-5-haiku-20241022", "claude-3-opus-20240229", "claude-3-sonnet-20240229", "claude-3-haiku-20240307", ];
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
pub enum ThinkingType {
Enabled,
#[default]
Disabled,
}
#[derive(Debug, Clone)]
pub struct ThinkingConfig {
pub budget_tokens: usize,
pub r#type: ThinkingType,
}
impl ThinkingConfig {
pub fn enabled(budget_tokens: usize) -> Self {
Self {
budget_tokens,
r#type: ThinkingType::Enabled,
}
}
pub fn disabled() -> Self {
Self {
budget_tokens: 0,
r#type: ThinkingType::Disabled,
}
}
pub fn is_enabled(&self) -> bool {
self.r#type == ThinkingType::Enabled
}
}
impl Default for ThinkingConfig {
fn default() -> Self {
Self::disabled()
}
}
#[derive(Debug, Clone)]
pub struct AnthropicConfig {
pub api_key: String,
pub base_url: String,
pub model: String,
pub max_tokens: usize,
pub temperature: Option<f32>,
pub system_prompt: Option<String>,
pub thinking: ThinkingConfig,
pub tools: Option<Vec<ToolDefinition>>,
pub tool_choice: Option<String>,
}
impl Default for AnthropicConfig {
fn default() -> Self {
Self {
api_key: String::new(),
base_url: ANTHROPIC_BASE_URL.to_string(),
model: "claude-3-5-sonnet-20241022".to_string(),
max_tokens: 4096,
temperature: None,
system_prompt: None,
thinking: ThinkingConfig::default(),
tools: None,
tool_choice: None,
}
}
}
impl AnthropicConfig {
pub fn new(api_key: impl Into<String>) -> Self {
Self {
api_key: api_key.into(),
..Default::default()
}
}
#[deprecated(
since = "0.7.0",
note = "Use from_env_result() which returns Result<Self, String>"
)]
#[allow(deprecated)]
pub fn from_env() -> Result<Self, String> {
Self::from_env_result()
}
pub fn from_env_result() -> Result<Self, String> {
let api_key = env::var("ANTHROPIC_API_KEY")
.map_err(|_| "ANTHROPIC_API_KEY environment variable not set".to_string())?;
let base_url =
env::var("ANTHROPIC_BASE_URL").unwrap_or_else(|_| ANTHROPIC_BASE_URL.to_string());
let model = env::var("ANTHROPIC_MODEL")
.unwrap_or_else(|_| "claude-3-5-sonnet-20241022".to_string());
let max_tokens = env::var("ANTHROPIC_MAX_TOKENS")
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(4096);
Ok(Self {
api_key,
base_url,
model,
max_tokens,
..Default::default()
})
}
pub fn with_model(mut self, model: impl Into<String>) -> Self {
self.model = model.into();
self
}
pub fn with_base_url(mut self, url: impl Into<String>) -> Self {
self.base_url = url.into();
self
}
pub fn with_max_tokens(mut self, max: usize) -> Self {
self.max_tokens = max;
self
}
pub fn with_temperature(mut self, temp: f32) -> Self {
self.temperature = Some(temp);
self
}
pub fn with_system_prompt(mut self, prompt: impl Into<String>) -> Self {
self.system_prompt = Some(prompt.into());
self
}
pub fn with_thinking(mut self, thinking: ThinkingConfig) -> Self {
self.thinking = thinking;
self
}
}