A comprehensive C++ application framework for connecting to multiple AI APIs with a unified interface. This project provides a robust, factory-pattern-based solution for managing connections to various AI service providers including Anthropic Claude, OpenAI, Google Gemini, and Cohere.
Version: 0.3.0 | C++ Standard: C++23 | License: MIT
This application demonstrates modern C++ design patterns for API integration, featuring:
- Multi-API Support: Unified interface for Anthropic Claude, OpenAI, Google Gemini, and Cohere APIs
- Factory Pattern Implementation: Clean, extensible design for creating API clients
- Configuration-Driven: JSON-based configuration system with local overrides
- Connection Pooling: Efficient HTTP connection management
- Error Handling: Comprehensive error handling and retry mechanisms
- Modern C++: Leverages C++23 features for clean, efficient code
- Cross-Platform: Builds on Windows, Linux, and macOS
The application follows a layered architecture with clear separation of concerns:
┌─────────────────────────────────────────┐
│ Main App │
├─────────────────────────────────────────┤
│ API Factory │
├─────────────────────────────────────────┤
│ Global API Interface (IApiClient) │
├─────────────────────────────────────────┤
│ AnthropicClient │ OpenAIClient │ etc. │
├─────────────────────────────────────────┤
│ HTTP Connection Pool │
├─────────────────────────────────────────┤
│ Configuration Manager │
└─────────────────────────────────────────┘
The base configuration template defining all supported APIs and their settings:
{
"apis": {
"anthropic": {
"name": "Anthropic Claude API",
"base_url": "https://api.anthropic.com",
"version": "v1",
"endpoints": {
"messages": "/v1/messages",
"models": "/v1/models"
},
"auth": {
"type": "header",
"header_name": "x-api-key",
"env_var": "ANTHROPIC_API_KEY"
},
"default_model": "claude-3-sonnet-20240229",
"max_tokens": 4096,
"timeout": 30000
}
}
}A copy of config.json that the application reads at runtime. This allows for:
- Local customization without affecting the template
- Environment-specific settings
- API key management through environment variables
- Testing with different configurations
Setup: Copy config.json to config.local and customize as needed:
cp config.json config.local| Provider | Status | Authentication | Models |
|---|---|---|---|
| Anthropic Claude | ✅ | API Key (Header) | claude-3-sonnet, claude-3-opus |
| OpenAI | ✅ | Bearer Token | gpt-4, gpt-3.5-turbo |
| Google Gemini | ✅ | API Key (Query) | gemini-pro |
| Cohere | ✅ | Bearer Token | command, command-r |
The framework supports multiple authentication patterns:
- Header-based: API key in custom header (Anthropic)
- Bearer Token: OAuth-style bearer authentication (OpenAI, Cohere)
- Query Parameter: API key as URL parameter (Gemini)
All API keys are loaded from environment variables for security.
- C++23 compatible compiler (GCC 13+, Clang 15+, MSVC 2022)
- CMake 3.10 or higher
- Development libraries:
- libcurl (for HTTP requests)
- nlohmann/json (for JSON parsing)
- OpenSSL (for HTTPS)
sudo apt update
sudo apt install build-essential cmake libcurl4-openssl-dev libssl-dev nlohmann-json3-devbrew install cmake curl openssl nlohmann-json# Using vcpkg
vcpkg install curl openssl nlohmann-json- Clone and configure:
git clone <repository-url>
cd PyClaudeCli
cp config.json config.local- Set up API keys:
export ANTHROPIC_API_KEY="your-anthropic-key"
export OPENAI_API_KEY="your-openai-key"
export GEMINI_API_KEY="your-gemini-key"
export COHERE_API_KEY="your-cohere-key"- Build the project:
# Quick build
./b
# Or manual CMake build
mkdir build && cd build
cmake .. -DCMAKE_CXX_COMPILER=clang++
make -j$(nproc)- Run tests:
./t # All tests
./t --cpp # C++ API tests only
./t --unit # Unit tests
./t --integration # Integration tests#include "api_factory.h"
#include "config_manager.h"
int main() {
// Load configuration
ConfigManager config("./config.local");
// Create API factory
ApiFactory factory(config);
// Get Anthropic client
auto claude_client = factory.createClient("anthropic");
if (claude_client) {
auto response = claude_client->sendMessage("Hello, Claude!");
std::cout << response << std::endl;
}
// Get OpenAI client
auto openai_client = factory.createClient("openai");
if (openai_client) {
auto response = openai_client->sendMessage("Hello, GPT!");
std::cout << response << std::endl;
}
return 0;
}// Custom configuration overrides
ConfigManager config("./config.local");
config.setApiTimeout("anthropic", 60000); // 60 second timeout
config.setMaxTokens("openai", 8192); // Increase token limit
// Use specific models
auto claude_client = factory.createClient("anthropic");
claude_client->setModel("claude-3-opus-20240229");
auto gpt_client = factory.createClient("openai");
gpt_client->setModel("gpt-4-turbo");try {
auto client = factory.createClient("anthropic");
auto response = client->sendMessage("Test message");
std::cout << "Response: " << response << std::endl;
} catch (const ApiException& e) {
std::cerr << "API Error: " << e.what() << std::endl;
} catch (const ConfigException& e) {
std::cerr << "Config Error: " << e.what() << std::endl;
} catch (const std::exception& e) {
std::cerr << "General Error: " << e.what() << std::endl;
}src/
├── api/
│ ├── base/
│ │ ├── IApiClient.h # Global API interface
│ │ ├── ApiException.h # Exception handling
│ │ └── HttpClient.h # HTTP client wrapper
│ ├── clients/
│ │ ├── AnthropicClient.h # Anthropic Claude implementation
│ │ ├── AnthropicClient.cpp
│ │ ├── OpenAIClient.h # OpenAI implementation
│ │ ├── OpenAIClient.cpp
│ │ ├── GeminiClient.h # Google Gemini implementation
│ │ ├── GeminiClient.cpp
│ │ ├── CohereClient.h # Cohere implementation
│ │ └── CohereClient.cpp
│ └── factory/
│ ├── ApiFactory.h # Factory pattern implementation
│ └── ApiFactory.cpp
├── config/
│ ├── ConfigManager.h # Configuration management
│ ├── ConfigManager.cpp
│ └── ApiConfig.h # Configuration structures
├── utils/
│ ├── ConnectionPool.h # HTTP connection pooling
│ ├── ConnectionPool.cpp
│ ├── Logger.h # Logging utilities
│ └── Logger.cpp
└── main.cpp # Application entry point
config.json # Configuration template
config.local # Runtime configuration (copy of config.json)
CMakeLists.txt # Build configuration
README.md # This file
The ApiFactory class implements the factory pattern to create appropriate API client instances:
class ApiFactory {
public:
std::unique_ptr<IApiClient> createClient(const std::string& provider);
private:
ConfigManager& config_;
std::map<std::string, std::function<std::unique_ptr<IApiClient>()>> creators_;
};Each API client implements the IApiClient interface, allowing interchangeable use:
class IApiClient {
public:
virtual ~IApiClient() = default;
virtual std::string sendMessage(const std::string& message) = 0;
virtual void setModel(const std::string& model) = 0;
virtual std::vector<std::string> getAvailableModels() = 0;
};The ConfigManager ensures single instance for configuration access:
class ConfigManager {
public:
static ConfigManager& getInstance();
ApiConfig getApiConfig(const std::string& provider);
private:
ConfigManager() = default;
static std::unique_ptr<ConfigManager> instance_;
};- Unit Tests: Individual component testing
- Integration Tests: API interaction testing
- Configuration Tests: Config loading and validation
- Factory Tests: Factory pattern verification
# All tests
./t
# Specific test categories
./t --unit
./t --integration
./t --cpp
# With coverage
./t --coverage
# Quick smoke test
./t --quickTests use mock configurations and can run without real API keys:
{
"test_mode": true,
"mock_responses": true,
"apis": {
"mock_anthropic": {
"base_url": "http://localhost:8080/mock"
}
}
}- Environment Variables: All API keys loaded from environment
- No Hardcoding: Keys never stored in source code or config files
- Secure Transmission: HTTPS only for all API communications
- Sanitization: All user inputs sanitized before API calls
- Size Limits: Message and response size limits enforced
- Rate Limiting: Built-in rate limiting to prevent abuse
- No Information Leakage: Error messages don't expose sensitive data
- Graceful Degradation: Fallback behavior for API failures
- Audit Logging: Optional logging for security monitoring
- Persistent Connections: Reuse HTTP connections for efficiency
- Connection Limits: Configurable connection pool sizes
- Timeout Management: Proper timeout handling for reliability
- Response Caching: Optional caching for repeated requests
- Model Metadata: Cache model information to reduce API calls
- Configuration Caching: In-memory config caching for performance
- RAII: Resource Acquisition Is Initialization pattern
- Smart Pointers: Automatic memory management
- Move Semantics: Efficient object transfer
- ERROR: Critical errors and exceptions
- WARN: Warning conditions and fallbacks
- INFO: General operational information
- DEBUG: Detailed debugging information
- Request Count: Track API usage per provider
- Response Times: Monitor API performance
- Error Rates: Track failure rates per API
- Connection Pool: Monitor connection utilization
Error: Failed to load config.local
Solution: Ensure config.local exists and is valid JSON
Error: 401 Unauthorized
Solution: Check API key environment variables
Error: Connection timeout
Solution: Check internet connectivity and API endpoints
Error: Could not find nlohmann/json
Solution: Install development dependencies
Enable debug logging for detailed troubleshooting:
Logger::setLevel(LogLevel::DEBUG);Or through configuration:
{
"logging": {
"level": "DEBUG",
"log_requests": true,
"log_responses": true
}
}- Fork the repository
- Create feature branch:
git checkout -b feature/amazing-feature - Install pre-commit hooks:
./setup-hooks.sh - Make changes and ensure tests pass
- Submit pull request
- C++23 Standard: Use modern C++ features
- Google Style: Follow Google C++ style guide
- Documentation: Doxygen comments for all public APIs
- Testing: Unit tests for all new functionality
- Version Bump: Update version in CMakeLists.txt
- Changelog: Update CHANGELOG.md with changes
- Testing: Run full test suite
- Tagging: Create git tag for release
- Documentation: Update documentation as needed
This project is licensed under the MIT License - see the LICENSE file for details.
- nlohmann/json: Excellent JSON library for C++
- libcurl: Reliable HTTP client library
- CMake: Modern build system
- AI API Providers: Anthropic, OpenAI, Google, Cohere for their excellent APIs
For more detailed information, see the individual component documentation in the docs/ directory.


