using System.Collections.Concurrent; using MeetingAssistant.Workflow; using Microsoft.Extensions.Options; namespace MeetingAssistant.MacOs; public sealed class MacOsWorkflowRulesEditorSessions { private readonly MacOsWorkflowRulesEditorSession defaultSession; private readonly ConcurrentDictionary sessions = new(StringComparer.Ordinal); private readonly ConcurrentDictionary windows = new(StringComparer.Ordinal); private readonly IWorkflowRulesEditorChatPipeline pipeline; private readonly string agentUrl; private readonly CancellationToken applicationStopping; private readonly ILogger logger; public MacOsWorkflowRulesEditorSessions( IWorkflowRulesEditorChatPipeline pipeline, IOptions options, IHostApplicationLifetime applicationLifetime, ILogger logger) { this.pipeline = pipeline; this.logger = logger; applicationStopping = applicationLifetime.ApplicationStopping; agentUrl = $"{options.Value.Api.PublicBaseUrl.TrimEnd('/')}/diagnostics/settings-and-logs"; defaultSession = CreateSession(); } public bool TryGetSession(string? id, out MacOsWorkflowRulesEditorSession session) { if (string.IsNullOrEmpty(id)) { session = defaultSession; return true; } return sessions.TryGetValue(id, out session!); } public IReadOnlyList GetAgentWindows() => applicationStopping.IsCancellationRequested ? [] : windows.Values.ToArray(); public void OpenWithPrompt(string initialPrompt) { ArgumentException.ThrowIfNullOrWhiteSpace(initialPrompt); applicationStopping.ThrowIfCancellationRequested(); var id = Guid.NewGuid().ToString("N"); var session = CreateSession(); sessions[id] = session; var task = session.SendAsync(initialPrompt, applicationStopping); windows[id] = new MacOsAgentWindowRequest(id, $"{agentUrl}?session={id}"); _ = ObservePromptAsync(task, id); } private MacOsWorkflowRulesEditorSession CreateSession() => new(new WorkflowRulesEditorChatViewModel(pipeline), applicationStopping); private async Task ObservePromptAsync(Task task, string id) { try { await task; } catch (OperationCanceledException) when (applicationStopping.IsCancellationRequested) { } catch (Exception exception) { logger.LogError(exception, "Could not start approved workflow conversation {SessionId}", id); } } } public sealed record MacOsAgentWindowRequest(string Id, string Url);