use crate::core::{GenericProvider, HttpClient, Protocol};
use crate::protocols::AnthropicProtocol;
use crate::error::LlmConnectorError;
use std::collections::HashMap;
pub type AnthropicProvider = GenericProvider<AnthropicProtocol>;
pub fn anthropic(api_key: &str) -> Result<AnthropicProvider, LlmConnectorError> {
anthropic_with_config(api_key, None, None, None)
}
pub fn anthropic_with_config(
api_key: &str,
base_url: Option<&str>,
timeout_secs: Option<u64>,
proxy: Option<&str>,
) -> Result<AnthropicProvider, LlmConnectorError> {
let protocol = AnthropicProtocol::new(api_key);
let client = HttpClient::with_config(
base_url.unwrap_or("https://api.anthropic.com"),
timeout_secs,
proxy,
)?;
let auth_headers: HashMap<String, String> = protocol.auth_headers().into_iter().collect();
let client = client.with_headers(auth_headers);
Ok(GenericProvider::new(protocol, client))
}
pub fn anthropic_vertex(
project_id: &str,
location: &str,
access_token: &str,
) -> Result<AnthropicProvider, LlmConnectorError> {
let protocol = AnthropicProtocol::new("");
let base_url = format!(
"https://{}-aiplatform.googleapis.com/v1/projects/{}/locations/{}/publishers/anthropic",
location, project_id, location
);
let client = HttpClient::new(&base_url)?
.with_header("Authorization".to_string(), format!("Bearer {}", access_token))
.with_header("Content-Type".to_string(), "application/json".to_string());
Ok(GenericProvider::new(protocol, client))
}
pub fn anthropic_bedrock(
region: &str,
_access_key_id: &str,
_secret_access_key: &str,
) -> Result<AnthropicProvider, LlmConnectorError> {
let protocol = AnthropicProtocol::new("");
let base_url = format!("https://bedrock-runtime.{}.amazonaws.com", region);
let client = HttpClient::new(&base_url)?
.with_header("Content-Type".to_string(), "application/json".to_string())
.with_header("X-Amz-Target".to_string(), "BedrockRuntime_20231002.InvokeModel".to_string());
Ok(GenericProvider::new(protocol, client))
}
pub fn anthropic_with_timeout(
api_key: &str,
timeout_secs: u64,
) -> Result<AnthropicProvider, LlmConnectorError> {
anthropic_with_config(api_key, None, Some(timeout_secs), None)
}
pub fn validate_anthropic_key(api_key: &str) -> bool {
api_key.starts_with("sk-ant-")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_anthropic_provider_creation() {
let provider = anthropic("sk-ant-test-key");
assert!(provider.is_ok());
let provider = provider.unwrap();
assert_eq!(provider.protocol().name(), "anthropic");
assert_eq!(provider.protocol().api_key(), "sk-ant-test-key");
}
#[test]
fn test_anthropic_with_config() {
let provider = anthropic_with_config(
"sk-ant-test-key",
Some("https://custom.anthropic.com"),
Some(60),
None
);
assert!(provider.is_ok());
let provider = provider.unwrap();
assert_eq!(provider.client().base_url(), "https://custom.anthropic.com");
}
#[test]
fn test_anthropic_vertex() {
let provider = anthropic_vertex(
"test-project",
"us-central1",
"test-token"
);
assert!(provider.is_ok());
}
#[test]
fn test_anthropic_bedrock() {
let provider = anthropic_bedrock(
"us-east-1",
"test-key-id",
"test-secret"
);
assert!(provider.is_ok());
}
#[test]
fn test_anthropic_with_timeout() {
let provider = anthropic_with_timeout("sk-ant-test-key", 120);
assert!(provider.is_ok());
}
#[test]
fn test_validate_anthropic_key() {
assert!(validate_anthropic_key("sk-ant-api03-test"));
assert!(validate_anthropic_key("sk-ant-test"));
assert!(!validate_anthropic_key("sk-test"));
assert!(!validate_anthropic_key("test"));
assert!(!validate_anthropic_key(""));
}
}