using Nexus.Api.Data; using Nexus.Api.Integrations; using Nexus.Api.Repositories; namespace Nexus.Api.Services; public sealed class OperationsService( IAgentRuntime runtime, IAgentService agentService, IProjectRepository projectRepo, ITaskRepository taskRepo, IActivityRepository activityRepo) : IOperationsService { public async Task GetSnapshotAsync(CancellationToken ct = default) { var runtimeTask = runtime.GetStatusAsync(ct); var agentsTask = agentService.GetAgentsAsync(ct); var projectsTask = projectRepo.GetAllAsync(ct); var tasksTask = taskRepo.GetAllAsync(ct); var activityTask = activityRepo.GetRecentAsync(20, ct); await Task.WhenAll(runtimeTask, agentsTask, projectsTask, tasksTask, activityTask); var tasks = tasksTask.Result; var projects = projectsTask.Result; var agents = agentsTask.Result; var completedTasks = tasks.Count(x => x.State == TaskStateHelper.ToStateString(TaskState.Done)); var runtimeStatus = runtimeTask.Result; var lastIncident = tasks .Where(x => x.State == TaskStateHelper.ToStateString(TaskState.Blocked)) .OrderByDescending(x => x.UpdatedAt) .Select(x => new { TaskId = (Guid?)x.Id, Title = (string?)x.Title, Since = (DateTimeOffset?)x.UpdatedAt }) .FirstOrDefault(); return new { generatedAt = DateTimeOffset.UtcNow, runtime = runtimeStatus, models = Array.Empty(), runtimeHealthy = runtimeStatus.Status == OperationalStatus.Online, metrics = new { activeAgents = agents.Count, queuedTasks = tasks.Count - completedTasks, successRate = tasks.Count == 0 ? 100 : Math.Round(completedTasks * 100d / tasks.Count, 1), incidents = tasks.Count(x => x.State == TaskStateHelper.ToStateString(TaskState.Blocked)) }, lastIncident, projectHealth = new { Online = projects.Count(x => x.Status == OperationalStatus.Online), Offline = projects.Count(x => x.Status == OperationalStatus.Offline), Degraded = projects.Count(x => x.Status == OperationalStatus.Degraded), Unknown = projects.Count(x => x.Status == OperationalStatus.Unknown) }, agents = agents.Select(x => new { x.Id, x.Name, x.Role, x.Status, x.Model }), projects = projects.Select(x => new { x.Id, x.Name, x.Status, x.Progress, x.UpdatedAt }), tasks = tasks.Select(x => new { x.Id, x.Title, x.State, x.Priority, x.ProjectId, x.UpdatedAt }), activity = activityTask.Result.Select(x => new { x.Id, x.Type, x.Message, at = x.CreatedAt }) }; } }