From 166988c41ff1dcf7b69a6f411fe475bb30727e5a Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Thu, 30 Jan 2025 11:10:15 -0600 Subject: [PATCH] Refactor Agemt Task --- .../Repositories/Filters/AgentTaskFilter.cs | 1 + .../{TaskExecutionStatus.cs => TaskStatus.cs} | 6 +- .../BotSharp.Abstraction/Tasks/ITaskFeeder.cs | 8 +++ .../Tasks/Models/AgentTask.cs | 46 ++++++--------- .../BotSharp.Core.Crontab/CrontabPlugin.cs | 3 + .../Services/CrontabService.cs | 59 ++++++++++++++++++- .../Services/AgentService.CreateAgent.cs | 1 - .../FileRepository.AgentTask.cs | 12 +--- .../Tasks/Services/AgentTaskService.cs | 22 +++++-- .../BotSharp.OpenAPI/BotSharp.OpenAPI.csproj | 3 +- .../Controllers/AgentTaskController.cs | 3 +- .../Controllers/DashboardController.cs | 6 -- .../Controllers/RulesController.cs | 1 - .../ViewModels/Agents/AgentTaskCreateModel.cs | 4 +- .../ViewModels/Agents/AgentTaskUpdateModel.cs | 4 +- .../ViewModels/Agents/AgentTaskViewModel.cs | 17 +++--- .../Repository/MongoRepository.AgentTask.cs | 8 --- 17 files changed, 128 insertions(+), 76 deletions(-) rename src/Infrastructure/BotSharp.Abstraction/Tasks/Enums/{TaskExecutionStatus.cs => TaskStatus.cs} (58%) create mode 100644 src/Infrastructure/BotSharp.Abstraction/Tasks/ITaskFeeder.cs diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/AgentTaskFilter.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/AgentTaskFilter.cs index 46ab4621..ac92321e 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/AgentTaskFilter.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/AgentTaskFilter.cs @@ -5,6 +5,7 @@ public class AgentTaskFilter public Pagination Pager { get; set; } = new Pagination(); public string? AgentId { get; set; } public bool? Enabled { get; set; } + public string? Status { get; set; } public static AgentTaskFilter Empty() { diff --git a/src/Infrastructure/BotSharp.Abstraction/Tasks/Enums/TaskExecutionStatus.cs b/src/Infrastructure/BotSharp.Abstraction/Tasks/Enums/TaskStatus.cs similarity index 58% rename from src/Infrastructure/BotSharp.Abstraction/Tasks/Enums/TaskExecutionStatus.cs rename to src/Infrastructure/BotSharp.Abstraction/Tasks/Enums/TaskStatus.cs index eb546682..f36d00a0 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Tasks/Enums/TaskExecutionStatus.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Tasks/Enums/TaskStatus.cs @@ -1,5 +1,9 @@ -public class TaskExecutionStatus +/// +/// Agent task status +/// +public class TaskStatus { + public const string Scheduled = "scheduled"; public const string New = "new"; public const string Running = "running"; public const string Success = "success"; diff --git a/src/Infrastructure/BotSharp.Abstraction/Tasks/ITaskFeeder.cs b/src/Infrastructure/BotSharp.Abstraction/Tasks/ITaskFeeder.cs new file mode 100644 index 00000000..7031077d --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Tasks/ITaskFeeder.cs @@ -0,0 +1,8 @@ +using BotSharp.Abstraction.Tasks.Models; + +namespace BotSharp.Abstraction.Tasks; + +public interface ITaskFeeder +{ + Task> GetTasks(); +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Tasks/Models/AgentTask.cs b/src/Infrastructure/BotSharp.Abstraction/Tasks/Models/AgentTask.cs index b3a6aaf2..e4852307 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Tasks/Models/AgentTask.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Tasks/Models/AgentTask.cs @@ -1,35 +1,27 @@ namespace BotSharp.Abstraction.Tasks.Models; -public class AgentTask : AgentTaskMetaData +public class AgentTask { - public string Id { get; set; } - public string Content { get; set; } - - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public string AgentId { get; set; } - - [JsonIgnore(Condition = JsonIgnoreCondition.Always)] - public Agent Agent { get; set; } - - public AgentTask() - { - - } - - public AgentTask(string id, string name, string? description = null) - { - Id = id; - Name = name; - Description = description; - } -} - -public class AgentTaskMetaData -{ - public string Name { get; set; } + public string Id { get; set; } = string.Empty; + public string Name { get; set; } = string.Empty; public string? Description { get; set; } public bool Enabled { get; set; } - public string? DirectAgentId { get; set; } + public string Content { get; set; } = string.Empty; + + [JsonIgnore(Condition = JsonIgnoreCondition.Always)] + public string AgentId { get; set; } = string.Empty; + + [JsonIgnore(Condition = JsonIgnoreCondition.Always)] + public Agent Agent { get; set; } = new(); + + /// + /// Agent task status + /// + public string Status { get; set; } = TaskStatus.New; + + public DateTime? LastExecutedDateTime { get; set; } + public DateTime? NextExecutionDateTime { get; set; } + public DateTime CreatedDateTime { get; set; } public DateTime UpdatedDateTime { get; set; } } diff --git a/src/Infrastructure/BotSharp.Core.Crontab/CrontabPlugin.cs b/src/Infrastructure/BotSharp.Core.Crontab/CrontabPlugin.cs index 9e220354..feef2546 100644 --- a/src/Infrastructure/BotSharp.Core.Crontab/CrontabPlugin.cs +++ b/src/Infrastructure/BotSharp.Core.Crontab/CrontabPlugin.cs @@ -14,6 +14,7 @@ limitations under the License. ******************************************************************************/ +using BotSharp.Abstraction.Tasks; using BotSharp.Core.Crontab.Hooks; namespace BotSharp.Core.Crontab; @@ -33,6 +34,8 @@ public class CrontabPlugin : IBotSharpPlugin { services.AddScoped(); services.AddScoped(); + services.AddScoped(); + services.AddHostedService(); services.AddHostedService(); } diff --git a/src/Infrastructure/BotSharp.Core.Crontab/Services/CrontabService.cs b/src/Infrastructure/BotSharp.Core.Crontab/Services/CrontabService.cs index e2ddc4bf..55e6da2c 100644 --- a/src/Infrastructure/BotSharp.Core.Crontab/Services/CrontabService.cs +++ b/src/Infrastructure/BotSharp.Core.Crontab/Services/CrontabService.cs @@ -15,8 +15,14 @@ ******************************************************************************/ using BotSharp.Abstraction.Repositories; +using BotSharp.Abstraction.Repositories.Filters; +using BotSharp.Abstraction.Tasks; +using BotSharp.Abstraction.Tasks.Models; +using BotSharp.Abstraction.Utilities; using BotSharp.Core.Infrastructures; +using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.Extensions.Logging; +using System.Text.RegularExpressions; namespace BotSharp.Core.Crontab.Services; @@ -24,7 +30,7 @@ namespace BotSharp.Core.Crontab.Services; /// The Crontab service schedules distributed events based on the execution times provided by users. /// In a scalable environment, distributed locks are used to ensure that each event is triggered only once. /// -public class CrontabService : ICrontabService +public class CrontabService : ICrontabService, ITaskFeeder { private readonly IServiceProvider _services; private ILogger _logger; @@ -52,6 +58,57 @@ public class CrontabService : ICrontabService return fixedCrantabItems; } + public async Task> GetTasks() + { + var agentService = _services.GetRequiredService(); + var tasks = new List(); + var cronsources = _services.GetServices(); + foreach (var source in cronsources) + { + var cron = source.GetCrontabItem(); + + // Get all agent subscribed to this cron + + var agents = await agentService.GetAgents(new AgentFilter + { + Pager = new Pagination + { + Size = 1000 + } + }); + + var preFilteredAgents = agents.Items.Where(x => + x.Rules.Exists(r => r.TriggerName == cron.Title)).ToList(); + + tasks.AddRange(preFilteredAgents.Select(x => new AgentTask + { + Id = Guid.Empty.ToString(), + AgentId = x.Id, + Agent = new BotSharp.Abstraction.Agents.Models.Agent + { + Name = x.Name, + Description = x.Description + }, + Name = FormatCrontabName(cron.Title, x.Name), + Content = $"Trigger: {cron.Title}\r\nAgent: {x.Name}\r\nCron expression: {cron.Cron}", + Status = TaskStatus.Scheduled, + Enabled = !x.Disabled, + Description = cron.Description, + LastExecutedDateTime = cron.LastExecutionTime + })); + } + + return tasks; + } + + private string FormatCrontabName(string trigger, string agent) + { + trigger = trigger.Replace("RuleTrigger", string.Empty); + trigger = Regex.Replace(trigger, "(? public async Task> GetTasks(AgentTaskFilter filter) { - var db = _services.GetRequiredService(); - var pagedTasks = db.GetAgentTasks(filter); - return await Task.FromResult(pagedTasks); + if (filter.Status == TaskStatus.Scheduled) + { + var taskFeeders = _services.GetServices(); + var items = taskFeeders.SelectMany(x => x.GetTasks().Result); + + return new PagedItems + { + Items = items, + Count = items.Count() + }; + } + else + { + var db = _services.GetRequiredService(); + var pagedTasks = db.GetAgentTasks(filter); + return await Task.FromResult(pagedTasks); + } } /// diff --git a/src/Infrastructure/BotSharp.OpenAPI/BotSharp.OpenAPI.csproj b/src/Infrastructure/BotSharp.OpenAPI/BotSharp.OpenAPI.csproj index 94a86637..ef06b4d5 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/BotSharp.OpenAPI.csproj +++ b/src/Infrastructure/BotSharp.OpenAPI/BotSharp.OpenAPI.csproj @@ -1,4 +1,4 @@ - + $(TargetFramework) @@ -47,7 +47,6 @@ - diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentTaskController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentTaskController.cs index 3d585378..1ff61f45 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentTaskController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentTaskController.cs @@ -38,10 +38,11 @@ public class AgentTaskController : ControllerBase [HttpGet("/agent/tasks")] public async Task> GetAgentTasks([FromQuery] AgentTaskFilter filter) { + filter.Status = TaskStatus.Scheduled; var tasks = await _agentTaskService.GetTasks(filter); return new PagedItems { - Items = tasks.Items.Select(x => AgentTaskViewModel.From(x)), + Items = tasks.Items.Select(AgentTaskViewModel.From), Count = tasks.Count }; } diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/DashboardController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/DashboardController.cs index f75467fe..0534b01d 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/DashboardController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/DashboardController.cs @@ -1,10 +1,4 @@ using BotSharp.Abstraction.Options; -using BotSharp.Abstraction.Users.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace BotSharp.OpenAPI.Controllers; diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/RulesController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/RulesController.cs index f135866f..0f58d9e5 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/RulesController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/RulesController.cs @@ -1,6 +1,5 @@ using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Rules; -using BotSharp.Core.Rules.Triggers; namespace BotSharp.OpenAPI.Controllers; diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskCreateModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskCreateModel.cs index 03410f18..89565e9f 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskCreateModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskCreateModel.cs @@ -8,7 +8,6 @@ public class AgentTaskCreateModel public string? Description { get; set; } public string Content { get; set; } public bool Enabled { get; set; } - public string? DirectAgentId { get; set; } public AgentTask ToAgentTask() { @@ -17,8 +16,7 @@ public class AgentTaskCreateModel Name = Name, Description = Description, Content = Content, - Enabled = Enabled, - DirectAgentId = DirectAgentId + Enabled = Enabled }; } } diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskUpdateModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskUpdateModel.cs index 5dcea21c..143aee0d 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskUpdateModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskUpdateModel.cs @@ -8,7 +8,6 @@ public class AgentTaskUpdateModel public string? Description { get; set; } public string? Content { get; set; } public bool Enabled { get; set; } - public string? DirectAgentId { get; set; } public AgentTask ToAgentTask() { @@ -17,8 +16,7 @@ public class AgentTaskUpdateModel Name = Name, Description = Description, Content = Content, - Enabled = Enabled, - DirectAgentId = DirectAgentId + Enabled = Enabled }; } } diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskViewModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskViewModel.cs index 1e77f250..6613e3dc 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskViewModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskViewModel.cs @@ -5,21 +5,22 @@ namespace BotSharp.OpenAPI.ViewModels.Agents; public class AgentTaskViewModel { - public string Id { get; set; } - public string Name { get; set; } + public string Id { get; set; } = null!; + public string Name { get; set; } = null!; public string? Description { get; set; } - public string Content { get; set; } + public string Content { get; set; } = null!; public bool Enabled { get; set; } + + public string Status { get; set; } = null!; + [JsonPropertyName("created_datetime")] public DateTime CreatedDateTime { get; set; } [JsonPropertyName("updated_datetime")] public DateTime UpdatedDateTime { get; set; } [JsonPropertyName("agent_id")] - public string AgentId { get; set; } + public string AgentId { get; set; } = null!; [JsonPropertyName("agent_name")] - public string AgentName { get; set; } - [JsonPropertyName("direct_agent_id")] - public string? DirectAgentId { get; set; } + public string AgentName { get; set; } = null!; public static AgentTaskViewModel From(AgentTask task) { @@ -32,7 +33,7 @@ public class AgentTaskViewModel Enabled = task.Enabled, AgentId = task.AgentId, AgentName = task.Agent?.Name, - DirectAgentId = task?.DirectAgentId, + Status = task.Status, CreatedDateTime = task.CreatedDateTime, UpdatedDateTime = task.UpdatedDateTime }; diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.AgentTask.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.AgentTask.cs index 2946b7b0..0c8e66e1 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.AgentTask.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.AgentTask.cs @@ -42,7 +42,6 @@ public partial class MongoRepository Description = x.Description, Enabled = x.Enabled, AgentId = x.AgentId, - DirectAgentId = x.DirectAgentId, Content = x.Content, CreatedDateTime = x.CreatedTime, UpdatedDateTime = x.UpdatedTime, @@ -73,7 +72,6 @@ public partial class MongoRepository Description = taskDoc.Description, Enabled = taskDoc.Enabled, AgentId = taskDoc.AgentId, - DirectAgentId = taskDoc.DirectAgentId, Content = taskDoc.Content, CreatedDateTime = taskDoc.CreatedTime, UpdatedDateTime = taskDoc.UpdatedTime, @@ -92,7 +90,6 @@ public partial class MongoRepository Description = task.Description, Enabled = task.Enabled, AgentId = task.AgentId, - DirectAgentId = task.DirectAgentId, Content = task.Content, CreatedTime = DateTime.UtcNow, UpdatedTime = DateTime.UtcNow @@ -112,7 +109,6 @@ public partial class MongoRepository Description = x.Description, Enabled = x.Enabled, AgentId = x.AgentId, - DirectAgentId = x.DirectAgentId, Content = x.Content, CreatedTime = x.CreatedDateTime, UpdatedTime = x.UpdatedDateTime @@ -143,15 +139,11 @@ public partial class MongoRepository case AgentTaskField.Content: taskDoc.Content = task.Content; break; - case AgentTaskField.DirectAgentId: - taskDoc.DirectAgentId = task.DirectAgentId; - break; case AgentTaskField.All: taskDoc.Name = task.Name; taskDoc.Description = task.Description; taskDoc.Enabled = task.Enabled; taskDoc.Content = task.Content; - taskDoc.DirectAgentId = task.DirectAgentId; break; }