using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; namespace MeetingAssistant.Workflow; public interface IMeetingWorkflowRulesProvider { Task> GetRulesAsync( MeetingAssistantOptions options, CancellationToken cancellationToken); } public sealed class FileMeetingWorkflowRulesProvider : IMeetingWorkflowRulesProvider { private readonly ILogger logger; private readonly IDeserializer yamlDeserializer = new DeserializerBuilder() .WithNamingConvention(UnderscoredNamingConvention.Instance) .IgnoreUnmatchedProperties() .Build(); public FileMeetingWorkflowRulesProvider(ILogger logger) { this.logger = logger; } public async Task> GetRulesAsync( MeetingAssistantOptions options, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(options.Automation.RulesPath)) { return []; } var path = WorkflowRulesPathResolver.Resolve(options.Automation.RulesPath); if (path is null) { return []; } if (!File.Exists(path)) { logger.LogDebug("Meeting workflow rules file {RulesPath} does not exist", path); return []; } var yaml = await File.ReadAllTextAsync(path, cancellationToken); if (string.IsNullOrWhiteSpace(yaml)) { return []; } var rulesFile = yamlDeserializer.Deserialize(yaml) ?? new MeetingWorkflowRulesFile(); return rulesFile.Rules; } }