Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ int main() {
}
```

The same retry-config overload is available from
`ai::anthropic::create_client` for Anthropic requests.

#### Using OpenAI-Compatible APIs (OpenRouter, etc.)

The OpenAI client can be used with any OpenAI-compatible API by specifying a custom base URL. This allows you to use alternative providers like OpenRouter, which offers access to multiple models through a unified API.
Expand Down
10 changes: 10 additions & 0 deletions include/ai/anthropic.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"Anthropic component not available. Link with ai::anthropic or ai::sdk to use Anthropic functionality."
#endif

#include "retry/retry_policy.h"
#include "types/client.h"

#include <optional>
Expand Down Expand Up @@ -57,6 +58,15 @@ Client create_client(const std::string& api_key);
/// @return Configured Anthropic client
Client create_client(const std::string& api_key, const std::string& base_url);

/// Create an Anthropic client with custom configuration and retry settings
/// @param api_key Anthropic API key
/// @param base_url Custom base URL (for Anthropic-compatible APIs)
/// @param retry_config Custom retry configuration
/// @return Configured Anthropic client
Client create_client(const std::string& api_key,
const std::string& base_url,
const retry::RetryConfig& retry_config);

/// Try to create an Anthropic client using environment variables
/// Reads API key from ANTHROPIC_API_KEY environment variable
/// @return Optional client - has value if environment variable is set, empty
Expand Down
19 changes: 16 additions & 3 deletions src/providers/anthropic/anthropic_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ namespace anthropic {

AnthropicClient::AnthropicClient(const std::string& api_key,
const std::string& base_url)
: AnthropicClient(api_key, base_url, std::optional<retry::RetryConfig>{}) {}

AnthropicClient::AnthropicClient(const std::string& api_key,
const std::string& base_url,
const retry::RetryConfig& retry_config)
: AnthropicClient(api_key,
base_url,
std::optional<retry::RetryConfig>(retry_config)) {}

AnthropicClient::AnthropicClient(const std::string& api_key,
const std::string& base_url,
std::optional<retry::RetryConfig> retry_config)
: BaseProviderClient(
providers::ProviderConfig{
.api_key = api_key,
Expand All @@ -23,11 +35,12 @@ AnthropicClient::AnthropicClient(const std::string& api_key,
.auth_header_name = "x-api-key",
.auth_header_prefix = "",
.extra_headers = {{"anthropic-version", "2023-06-01"}},
.retry_config = std::nullopt},
.retry_config = retry_config},
std::make_unique<AnthropicRequestBuilder>(),
std::make_unique<AnthropicResponseParser>()) {
ai::logger::log_debug("Anthropic client initialized with base_url: {}",
base_url);
ai::logger::log_debug("Anthropic client initialized with base_url: {}{}",
base_url,
config_.retry_config ? " and custom retry config" : "");
}

StreamResult AnthropicClient::stream_text(const StreamOptions& options) {
Expand Down
11 changes: 11 additions & 0 deletions src/providers/anthropic/anthropic_client.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#pragma once

#include "ai/retry/retry_policy.h"
#include "ai/types/stream_options.h"
#include "providers/base_provider_client.h"

#include <optional>
#include <string>
#include <vector>

Expand All @@ -15,6 +17,10 @@ class AnthropicClient : public providers::BaseProviderClient {
const std::string& api_key,
const std::string& base_url = "https://api.anthropic.com");

AnthropicClient(const std::string& api_key,
const std::string& base_url,
const retry::RetryConfig& retry_config);

// Override only what's specific to Anthropic
StreamResult stream_text(const StreamOptions& options) override;
std::string provider_name() const override;
Expand All @@ -26,6 +32,11 @@ class AnthropicClient : public providers::BaseProviderClient {
// Member access for testing
const std::string& get_api_key() const { return config_.api_key; }
const std::string& get_base_url() const { return config_.base_url; }

private:
AnthropicClient(const std::string& api_key,
const std::string& base_url,
std::optional<retry::RetryConfig> retry_config);
};

} // namespace anthropic
Expand Down
8 changes: 8 additions & 0 deletions src/providers/anthropic/anthropic_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ Client create_client(const std::string& api_key, const std::string& base_url) {
get_api_key_or_default(api_key), get_base_url_or_default(base_url)));
}

Client create_client(const std::string& api_key,
const std::string& base_url,
const retry::RetryConfig& retry_config) {
return Client(std::make_unique<AnthropicClient>(
get_api_key_or_default(api_key), get_base_url_or_default(base_url),
retry_config));
}

std::optional<Client> try_create_client() {
auto api_key = utils::non_empty_env("ANTHROPIC_API_KEY");
if (!api_key) {
Expand Down
11 changes: 11 additions & 0 deletions tests/unit/anthropic_client_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,17 @@ TEST_F(AnthropicClientTest, ConstructorWithHttpUrl) {
// EXPECT_FALSE(client.get_use_ssl());
}

TEST_F(AnthropicClientTest, ConstructorWithCustomRetryConfig) {
retry::RetryConfig retry_config;
retry_config.max_retries = 5;

ai::anthropic::AnthropicClient client(
"sk-ant-test", "https://api.anthropic.com", retry_config);

EXPECT_TRUE(client.is_valid());
EXPECT_EQ(client.get_base_url(), "https://api.anthropic.com");
}

// Model Support Tests
TEST_F(AnthropicClientTest, SupportedModelsContainsExpectedModels) {
auto models = client_->supported_models();
Expand Down
Loading