DeutschLernen/GermanApp/Infrastructure/Configuration/MistralConfig.cs
Lasse Rune Hansen 2b11367a97
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
feat(backend/infrastructure): implement Mistral API Connector (Phase 0 of AI Services)
- Add Domain/Interfaces/IMistralConnector.cs with AiServiceException and AiErrorCode enum
- Add Infrastructure/Configuration/MistralConfig.cs with validation
- Add Infrastructure/Services/MistralConnector.cs with HTTP client implementation
- Add Infrastructure/Services/MistralRateLimiter.cs for rate limiting
- Add Infrastructure/Services/MistralCircuitBreaker.cs for circuit breaker pattern
- Add Application/Models/MistralRequest.cs with request models
- Add Application/Models/MistralResponse.cs with response models
- Update Program.cs to register IMistralConnector with MemoryCache, HttpClient, and config
- Update GermanApp.csproj with existing dependencies
- Update docs/features/ai-services.md with Phase 0 completion

Phase 0 of AI Services feature is complete. Mistral API Connector is ready for use by MistralService.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-09 18:56:37 +02:00

119 lines
3.4 KiB
C#

namespace GermanApp.Infrastructure.Configuration;
/// <summary>
/// Configuration settings for Mistral API connector.
/// This is part of the Infrastructure layer.
/// </summary>
public class MistralConfig
{
/// <summary>
/// The Mistral API key for authentication.
/// </summary>
public string ApiKey { get; set; } = string.Empty;
/// <summary>
/// The base URL for the Mistral API.
/// Default: https://api.mistral.ai/v1/
/// </summary>
public string BaseUrl { get; set; } = "https://api.mistral.ai/v1/";
/// <summary>
/// The default model to use for completions.
/// Default: mistral-medium
/// </summary>
public string DefaultModel { get; set; } = "mistral-medium";
/// <summary>
/// Timeout in seconds for HTTP requests.
/// Default: 30 seconds
/// </summary>
public int TimeoutSeconds { get; set; } = 30;
/// <summary>
/// Maximum number of retry attempts for failed requests.
/// Default: 3
/// </summary>
public int MaxRetries { get; set; } = 3;
/// <summary>
/// Maximum requests per minute rate limit.
/// Default: 10 requests/minute
/// </summary>
public int RateLimitPerMinute { get; set; } = 10;
/// <summary>
/// Whether to enable response caching.
/// Default: true
/// </summary>
public bool EnableCaching { get; set; } = true;
/// <summary>
/// Cache time-to-live in minutes.
/// Default: 60 minutes
/// </summary>
public int CacheTTLMinutes { get; set; } = 60;
/// <summary>
/// Circuit breaker failure threshold (number of consecutive failures before opening).
/// Default: 5
/// </summary>
public int CircuitBreakerFailureThreshold { get; set; } = 5;
/// <summary>
/// Circuit breaker reset timeout in minutes.
/// Default: 1 minute
/// </summary>
public int CircuitBreakerResetMinutes { get; set; } = 1;
/// <summary>
/// Validates the configuration.
/// </summary>
/// <exception cref="ArgumentException">Thrown when configuration is invalid</exception>
public void Validate()
{
if (string.IsNullOrWhiteSpace(ApiKey))
{
throw new ArgumentException("Mistral API key is required");
}
if (string.IsNullOrWhiteSpace(BaseUrl))
{
throw new ArgumentException("Mistral BaseUrl is required");
}
if (!Uri.TryCreate(BaseUrl, UriKind.Absolute, out _))
{
throw new ArgumentException("Mistral BaseUrl must be a valid URL");
}
if (TimeoutSeconds <= 0)
{
throw new ArgumentException("TimeoutSeconds must be greater than 0");
}
if (MaxRetries < 0)
{
throw new ArgumentException("MaxRetries must be non-negative");
}
if (RateLimitPerMinute <= 0)
{
throw new ArgumentException("RateLimitPerMinute must be greater than 0");
}
if (CacheTTLMinutes < 0)
{
throw new ArgumentException("CacheTTLMinutes must be non-negative");
}
if (CircuitBreakerFailureThreshold <= 0)
{
throw new ArgumentException("CircuitBreakerFailureThreshold must be greater than 0");
}
if (CircuitBreakerResetMinutes <= 0)
{
throw new ArgumentException("CircuitBreakerResetMinutes must be greater than 0");
}
}
}