Add Luna.Configuration with TOML-based agent and provider config
Implement configuration system with embedded TOML resources for agent and provider definitions, custom IConfigurationSource/Provider for agent and provider options, and DI extension methods. Includes config models for agents, providers, sessions, and Telegram integration.
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Luna.Configuration.Services.Agents;
|
||||
|
||||
internal class AgentOptionsConfigurationProvider(IEnumerable<AgentOptions> agentOptions) : ConfigurationProvider
|
||||
{
|
||||
public override void Load()
|
||||
{
|
||||
foreach (var options in agentOptions)
|
||||
{
|
||||
var keyPrefix = $"Agents:{options.Name}";
|
||||
|
||||
foreach (var property in options.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
|
||||
{
|
||||
Data[$"{keyPrefix}:{property.Name}"] = property.GetValue(options)?.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Luna.Configuration.Services.Agents;
|
||||
|
||||
internal class AgentOptionsConfigurationSource(string? searchPath = null)
|
||||
: IConfigurationSource
|
||||
{
|
||||
private readonly AgentOptionsProvider optionsProvider = new(searchPath);
|
||||
|
||||
public IConfigurationProvider Build(IConfigurationBuilder builder)
|
||||
=> new AgentOptionsConfigurationProvider(optionsProvider.GetAgentOptions());
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using Tomlyn;
|
||||
|
||||
namespace Luna.Configuration.Services.Agents;
|
||||
|
||||
internal sealed class AgentOptionsProvider(string? searchPath = null)
|
||||
{
|
||||
private readonly EmbeddedResourceLoader embeddedResourceLoader = new();
|
||||
|
||||
public IEnumerable<AgentOptions> GetAgentOptions()
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(searchPath)
|
||||
? GetAgentOptionsFromEmbeddedResources()
|
||||
: GetAgentOptionsFromFiles();
|
||||
}
|
||||
|
||||
private IEnumerable<AgentOptions> GetAgentOptionsFromFiles()
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrEmpty(searchPath);
|
||||
|
||||
var files = Directory.Exists(searchPath)
|
||||
? Directory.EnumerateFiles(searchPath, "Agent.*.toml")
|
||||
: [];
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
using var reader = File.OpenText(file);
|
||||
var agentOptions = TomlSerializer.Deserialize<AgentOptions>(reader);
|
||||
|
||||
yield return agentOptions
|
||||
?? throw new FormatException($"Invalid agent config file: {file}");
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<AgentOptions> GetAgentOptionsFromEmbeddedResources()
|
||||
{
|
||||
var resources = embeddedResourceLoader.ListResources("Agent.*.toml");
|
||||
foreach (var resource in resources)
|
||||
{
|
||||
var content = embeddedResourceLoader.LoadAsync(resource).GetAwaiter().GetResult();
|
||||
var agentOptions = TomlSerializer.Deserialize<AgentOptions>(content);
|
||||
|
||||
yield return agentOptions
|
||||
?? throw new FormatException($"Invalid agent config embedded resource: {resource}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static partial class StringExtensions
|
||||
{
|
||||
[GeneratedRegex(@"Agent\.(.+)\.toml", RegexOptions.IgnoreCase | RegexOptions.Compiled)]
|
||||
private static partial Regex AgentNameRegex { get; }
|
||||
|
||||
extension(string str)
|
||||
{
|
||||
public string ToAgentName() => AgentNameRegex.Match(str) is { Success: true } match
|
||||
? match.Groups[1].Value
|
||||
: throw new FormatException($"Invalid agent config file name: {str}");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user