92 lines
2.9 KiB
C#
92 lines
2.9 KiB
C#
using System.Text.Json;
|
|
using Intendant.Shared.Services;
|
|
|
|
namespace Intendant.Web.Services;
|
|
|
|
public sealed class OpenAiSettingsService : IOpenAiSettingsService
|
|
{
|
|
private readonly SemaphoreSlim _lock = new(1, 1);
|
|
private readonly OpenAiResponsesOptions _defaults;
|
|
private readonly string _filePath;
|
|
private OpenAiResponsesOptions? _cache;
|
|
|
|
public OpenAiSettingsService(IConfiguration configuration, IWebHostEnvironment environment)
|
|
{
|
|
_defaults = configuration.GetSection(OpenAiResponsesOptions.SectionName).Get<OpenAiResponsesOptions>() ?? new OpenAiResponsesOptions();
|
|
|
|
string directoryPath = Path.Combine(environment.ContentRootPath, "App_Data");
|
|
_filePath = Path.Combine(directoryPath, "openai-settings.json");
|
|
}
|
|
|
|
public async Task<OpenAiResponsesOptions> GetAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
await _lock.WaitAsync(cancellationToken);
|
|
try
|
|
{
|
|
if (_cache is not null)
|
|
{
|
|
return Clone(_cache);
|
|
}
|
|
|
|
if (!File.Exists(_filePath))
|
|
{
|
|
_cache = Clone(_defaults);
|
|
return Clone(_cache);
|
|
}
|
|
|
|
await using FileStream stream = File.OpenRead(_filePath);
|
|
OpenAiResponsesOptions? stored = await JsonSerializer.DeserializeAsync<OpenAiResponsesOptions>(stream, cancellationToken: cancellationToken);
|
|
_cache = Normalize(stored ?? new OpenAiResponsesOptions());
|
|
|
|
return Clone(_cache);
|
|
}
|
|
finally
|
|
{
|
|
_lock.Release();
|
|
}
|
|
}
|
|
|
|
public async Task SaveAsync(OpenAiResponsesOptions options, CancellationToken cancellationToken = default)
|
|
{
|
|
OpenAiResponsesOptions normalized = Normalize(options);
|
|
|
|
await _lock.WaitAsync(cancellationToken);
|
|
try
|
|
{
|
|
string? directory = Path.GetDirectoryName(_filePath);
|
|
if (!string.IsNullOrWhiteSpace(directory))
|
|
{
|
|
Directory.CreateDirectory(directory);
|
|
}
|
|
|
|
await using FileStream stream = File.Create(_filePath);
|
|
await JsonSerializer.SerializeAsync(stream, normalized, cancellationToken: cancellationToken);
|
|
_cache = Clone(normalized);
|
|
}
|
|
finally
|
|
{
|
|
_lock.Release();
|
|
}
|
|
}
|
|
|
|
private OpenAiResponsesOptions Normalize(OpenAiResponsesOptions options)
|
|
{
|
|
return new OpenAiResponsesOptions
|
|
{
|
|
ApiKey = options.ApiKey?.Trim() ?? string.Empty,
|
|
Endpoint = options.Endpoint?.Trim() ?? string.Empty,
|
|
Model = string.IsNullOrWhiteSpace(options.Model) ? _defaults.Model : options.Model.Trim(),
|
|
};
|
|
}
|
|
|
|
private static OpenAiResponsesOptions Clone(OpenAiResponsesOptions source)
|
|
{
|
|
return new OpenAiResponsesOptions
|
|
{
|
|
ApiKey = source.ApiKey,
|
|
Endpoint = source.Endpoint,
|
|
Model = source.Model,
|
|
};
|
|
}
|
|
}
|