using Microsoft.EntityFrameworkCore; using Nexus.Api.Data; namespace Nexus.Api.Repositories; public sealed class ActivityRepository(NexusDbContext db, Nexus.Api.Services.ILiveUpdateService liveUpdates) : IActivityRepository { public Task> GetRecentAsync(int take, CancellationToken ct = default) => db.Activity.AsNoTracking().OrderByDescending(x => x.CreatedAt).Take(take).ToListAsync(ct); public Task> GetRecentForTasksAsync(IEnumerable taskIds, CancellationToken ct = default) { var ids = taskIds.Distinct().ToList(); if (ids.Count == 0) return Task.FromResult(new List()); return db.Activity.AsNoTracking() .Where(x => x.TaskId.HasValue && ids.Contains(x.TaskId.Value)) .OrderByDescending(x => x.CreatedAt) .ToListAsync(ct); } public async Task<(List Items, int TotalCount)> GetPagedAsync( string? type, string? sort, int page, int pageSize, CancellationToken ct = default) { var query = db.Activity.AsNoTracking(); if (!string.IsNullOrWhiteSpace(type)) query = query.Where(x => x.Type == type); query = (sort?.ToLowerInvariant()) switch { "oldest" => query.OrderBy(x => x.CreatedAt), _ => query.OrderByDescending(x => x.CreatedAt) }; var totalCount = await query.CountAsync(ct); var items = await query.Skip((page - 1) * pageSize).Take(pageSize).ToListAsync(ct); return (items, totalCount); } public async Task> GetByAgentAsync(string agentId, int take, CancellationToken ct = default) { var candidateCount = Math.Max(take * 8, 100); var recent = await db.Activity.AsNoTracking() .OrderByDescending(x => x.CreatedAt) .Take(candidateCount) .ToListAsync(ct); return recent .Where(x => Nexus.Api.Services.AgentActivityText.MatchesAgent(x.Message, agentId)) .Take(take) .ToList(); } public async Task AddAsync(ActivityEvent activity, CancellationToken ct = default) { var agentIds = Nexus.Api.Services.AgentActivityText.ExtractAgentIds(activity.Message); activity.Message = Nexus.Api.Services.AgentActivityText.RedactForDisplay(activity.Message); db.Activity.Add(activity); await db.SaveChangesAsync(ct); liveUpdates.Publish("activity.created", new { activity.Id, activity.Type, activity.Message, activity.TaskId, activity.CreatedAt, agentIds }, "activity"); return activity; } }