using System; using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Text.Json; using System.Threading.Tasks; using Microsoft.Extensions.Configuration; namespace Mindforge.API.Providers { public class OpenAIApiProvider : ILlmApiProvider { private readonly HttpClient _httpClient; private readonly IConfiguration _configuration; private readonly ILogger _logger; public OpenAIApiProvider(HttpClient httpClient, IConfiguration configuration, ILogger logger) { _httpClient = httpClient; _httpClient.Timeout = TimeSpan.FromMinutes(5); _configuration = configuration; _logger = logger; } public async Task SendRequestAsync(string systemPrompt, string userPrompt, string model) { var apiKey = _configuration["OPENAI_API_KEY"]; if (string.IsNullOrEmpty(apiKey)) { throw new Exception("OPENAI_API_KEY not found in configuration."); } var apiBase = "https://api.openai.com/v1"; var url = $"{apiBase.TrimEnd('/')}/responses"; var reqBody = new { model = model, input = new[] { new { role = "developer", content = systemPrompt }, new { role = "user", content = userPrompt } }, reasoning = new { effort = "low" } }; var jsonBody = JsonSerializer.Serialize(reqBody); Exception? lastErr = null; for (int i = 0; i < 5; i++) { using var request = new HttpRequestMessage(HttpMethod.Post, url); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", apiKey); request.Content = new StringContent(jsonBody, Encoding.UTF8, "application/json"); try { var response = await _httpClient.SendAsync(request); var responseBody = await response.Content.ReadAsStringAsync(); if (!response.IsSuccessStatusCode) { lastErr = new Exception($"OpenAI API error status {(int)response.StatusCode}: {responseBody}"); await Task.Delay(TimeSpan.FromSeconds(1 << i)); continue; } var result = JsonSerializer.Deserialize(responseBody); if (result.TryGetProperty("output", out var outputArray)) { foreach (var outputItem in outputArray.EnumerateArray()) { if (outputItem.TryGetProperty("content", out var contentArray)) { foreach (var contentItem in contentArray.EnumerateArray()) { if (contentItem.TryGetProperty("text", out var textContent)) { return textContent.GetString() ?? string.Empty; } } } } } _logger.LogWarning("OpenAI API raw response: {responseBody}", responseBody); throw new Exception("empty response from OpenAI API"); } catch (Exception ex) { _logger.LogError(ex, "Error in OpenAI API request"); lastErr = ex; await Task.Delay(TimeSpan.FromSeconds(1 << i)); } } throw new Exception($"failed to get OpenAI response after 5 attempts. Last error: {lastErr?.Message}", lastErr); } public async Task SendRequestBatchAsync(string systemPrompt, string userPrompt, string model) { throw new NotImplementedException(); } } }