All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- 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>
119 lines
3.4 KiB
C#
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");
|
|
}
|
|
}
|
|
}
|