From e7223f126793ef178c71d244b20551f58ade3447 Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Sun, 4 Feb 2024 14:01:56 -0600 Subject: [PATCH] add update agent task --- .../Agents/Enums/AgentField.cs | 9 ++ .../Repositories/Filters/AgentTaskFilter.cs | 1 + .../Repositories/IBotSharpRepository.cs | 2 +- .../Tasks/IAgentTaskService.cs | 2 + .../Repository/BotSharpDbContext.cs | 5 + .../FileRepository.AgentTask.cs | 110 +++++++++++++++--- .../Tasks/Services/AgentTaskService.cs | 7 ++ .../Controllers/AgentTaskController.cs | 16 ++- .../ViewModels/Agents/AgentTaskUpdateModel.cs | 22 ++++ .../ViewModels/Agents/AgentTaskViewModel.cs | 4 +- .../Repository/MongoRepository.AgentTask.cs | 39 +++++++ 11 files changed, 195 insertions(+), 22 deletions(-) create mode 100644 src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskUpdateModel.cs diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs index 81aacb85..190b6cb8 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs @@ -18,3 +18,12 @@ public enum AgentField Sample, LlmConfig } + +public enum AgentTaskField +{ + All = 1, + Name, + Description, + Enabled, + Content +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/AgentTaskFilter.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/AgentTaskFilter.cs index a7b16b34..2d8ba477 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/AgentTaskFilter.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/AgentTaskFilter.cs @@ -4,4 +4,5 @@ public class AgentTaskFilter { public Pagination Pager { get; set; } = new Pagination(); public string? AgentId { get; set; } + public bool? Enabled { get; set; } } diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs index 459d8557..709958db 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs @@ -39,7 +39,7 @@ public interface IBotSharpRepository PagedItems GetAgentTasks(AgentTaskFilter filter); AgentTask? GetAgentTask(string agentId, string taskId); void InsertAgentTask(AgentTask task); - + void UpdateAgentTask(AgentTask task, AgentTaskField field); bool DeleteAgentTask(string agentId, string taskId); #endregion diff --git a/src/Infrastructure/BotSharp.Abstraction/Tasks/IAgentTaskService.cs b/src/Infrastructure/BotSharp.Abstraction/Tasks/IAgentTaskService.cs index 4ca48a84..34199ecc 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Tasks/IAgentTaskService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Tasks/IAgentTaskService.cs @@ -11,5 +11,7 @@ public interface IAgentTaskService Task CreateTask(AgentTask task); + Task UpdateTask(AgentTask task, AgentTaskField field); + Task DeleteTask(string agentId, string taskId); } diff --git a/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs b/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs index 0f109358..de71e1d1 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs @@ -136,6 +136,11 @@ public class BotSharpDbContext : Database, IBotSharpRepository throw new NotImplementedException(); } + public void UpdateAgentTask(AgentTask task, AgentTaskField field) + { + throw new NotImplementedException(); + } + public bool DeleteAgentTask(string agentId, string taskId) { throw new NotImplementedException(); diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.AgentTask.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.AgentTask.cs index d04855a3..c99c49e9 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.AgentTask.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.AgentTask.cs @@ -1,6 +1,7 @@ using BotSharp.Abstraction.Repositories.Filters; using BotSharp.Abstraction.Tasks.Models; using System.IO; +using System.Threading.Tasks; namespace BotSharp.Core.Repository; @@ -22,21 +23,39 @@ public partial class FileRepository var agentId = agentDir.Split(Path.DirectorySeparatorChar).Last(); var matched = true; - if (filter?.AgentId != null) matched = matched && agentId == filter.AgentId; + + if (filter?.AgentId != null) + { + matched = matched && agentId == filter.AgentId; + } if (!matched) continue; - var agent = ParseAgent(agentDir); - + var curTasks = new List(); foreach (var taskFile in Directory.GetFiles(taskDir)) { var task = ParseAgentTask(taskFile); if (task == null) continue; - task.AgentId = agentId; - task.Agent = agent; - tasks.Add(task); + if (filter?.Enabled != null) + { + matched = matched && task.Enabled == filter.Enabled; + } + + if (!matched) continue; + + curTasks.Add(task); } + + if (curTasks.IsNullOrEmpty()) continue; + + var agent = ParseAgent(agentDir); + curTasks.ForEach(t => + { + t.AgentId = agentId; + t.Agent = agent; + }); + tasks.AddRange(curTasks); } return new PagedItems @@ -54,12 +73,8 @@ public partial class FileRepository var taskDir = Path.Combine(agentDir, "tasks"); if (!Directory.Exists(taskDir)) return null; - var taskFile = Directory.GetFiles(taskDir).FirstOrDefault(file => - { - var fileName = file.Split(Path.DirectorySeparatorChar).Last(); - var id = fileName.Split('.').First(); - return id.IsEqualTo(taskId); - }); + var taskFile = FindTaskFileById(taskDir, taskId); + if (taskFile == null) return null; var task = ParseAgentTask(taskFile); if (task == null) return null; @@ -95,12 +110,60 @@ public partial class FileRepository UpdatedDateTime = DateTime.UtcNow }; - var fileContent = $"{AGENT_TASK_PREFIX}\n{JsonSerializer.Serialize(model, _options)}\n{AGENT_TASK_SUFFIX}\n\n{task.Content}"; + var fileContent = BuildAgentTaskFileContent(model, task.Content); File.WriteAllText(taskFile, fileContent); } - public void UpdateAgentTask() + public void UpdateAgentTask(AgentTask task, AgentTaskField field) { + if (task == null || string.IsNullOrEmpty(task.Id)) return; + + var agentDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, task.AgentId); + if (!Directory.Exists(agentDir)) return; + + var taskDir = Path.Combine(agentDir, "tasks"); + if (!Directory.Exists(taskDir)) return; + + var taskFile = FindTaskFileById(taskDir, task.Id); + if (string.IsNullOrEmpty(taskFile)) return; + + var parsedTask = ParseAgentTask(taskFile); + if (parsedTask == null) return; + + var model = new AgentTaskFileModel + { + Name = parsedTask.Name, + Description = parsedTask.Description, + Enabled = parsedTask.Enabled, + CreatedDateTime = parsedTask.CreatedDateTime, + UpdatedDateTime = DateTime.UtcNow + }; + var content = parsedTask.Content; + + switch (field) + { + case AgentTaskField.Name: + model.Name = task.Name; + break; + case AgentTaskField.Description: + model.Description = task.Description; + break; + case AgentTaskField.Enabled: + model.Enabled = task.Enabled; + break; + case AgentTaskField.Content: + content = task.Content; + break; + case AgentTaskField.All: + model.Name = task.Name; + model.Description = task.Description; + model.Enabled = task.Enabled; + content = task.Content; + break; + } + + var fileContent = BuildAgentTaskFileContent(model, content); + File.WriteAllText(taskFile, fileContent); } public bool DeleteAgentTask(string agentId, string taskId) @@ -111,6 +174,17 @@ public partial class FileRepository var taskDir = Path.Combine(agentDir, "tasks"); if (!Directory.Exists(taskDir)) return false; + var taskFile = FindTaskFileById(taskDir, taskId); + if (string.IsNullOrWhiteSpace(taskFile)) return false; + + File.Delete(taskFile); + return true; + } + + private string? FindTaskFileById(string taskDir, string taskId) + { + if (!Directory.Exists(taskDir) || string.IsNullOrEmpty(taskId)) return null; + var taskFile = Directory.GetFiles(taskDir).FirstOrDefault(file => { var fileName = file.Split(Path.DirectorySeparatorChar).Last(); @@ -118,10 +192,12 @@ public partial class FileRepository return id.IsEqualTo(taskId); }); - if (string.IsNullOrWhiteSpace(taskFile)) return false; + return taskFile; + } - File.Delete(taskFile); - return true; + private string BuildAgentTaskFileContent(AgentTaskFileModel fileModel, string taskContent) + { + return $"{AGENT_TASK_PREFIX}\n{JsonSerializer.Serialize(fileModel, _options)}\n{AGENT_TASK_SUFFIX}\n\n{taskContent}"; } #endregion } diff --git a/src/Infrastructure/BotSharp.Core/Tasks/Services/AgentTaskService.cs b/src/Infrastructure/BotSharp.Core/Tasks/Services/AgentTaskService.cs index 8323a957..5a4c182f 100644 --- a/src/Infrastructure/BotSharp.Core/Tasks/Services/AgentTaskService.cs +++ b/src/Infrastructure/BotSharp.Core/Tasks/Services/AgentTaskService.cs @@ -34,6 +34,13 @@ public class AgentTaskService : IAgentTaskService await Task.CompletedTask; } + public async Task UpdateTask(AgentTask task, AgentTaskField field) + { + var db = _services.GetRequiredService(); + db.UpdateAgentTask(task, field); + await Task.CompletedTask; + } + public async Task DeleteTask(string agentId, string taskId) { var db = _services.GetRequiredService(); diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentTaskController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentTaskController.cs index 0f858f21..95ad902d 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentTaskController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentTaskController.cs @@ -44,9 +44,21 @@ public class AgentTaskController : ControllerBase } [HttpPut("/agent/{agentId}/task/{taskId}")] - public async Task UpdateAgentTask([FromRoute] string agentId, [FromRoute] string taskId) + public async Task UpdateAgentTask([FromRoute] string agentId, [FromRoute] string taskId, [FromBody] AgentTaskUpdateModel task) { - throw new NotImplementedException(""); + var agentTask = task.ToAgentTask(); + agentTask.AgentId = agentId; + agentTask.Id = taskId; + await _agentTaskService.UpdateTask(agentTask, AgentTaskField.All); + } + + [HttpPatch("/agent/{agentId}/task/{taskId}/{field}")] + public async Task PatchAgentTaskByField([FromRoute] string agentId, [FromRoute] string taskId, [FromRoute] AgentTaskField field, [FromBody] AgentTaskUpdateModel task) + { + var agentTask = task.ToAgentTask(); + agentTask.AgentId = agentId; + agentTask.Id = taskId; + await _agentTaskService.UpdateTask(agentTask, field); } [HttpDelete("/agent/{agentId}/task/{taskId}")] diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskUpdateModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskUpdateModel.cs new file mode 100644 index 00000000..143aee0d --- /dev/null +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskUpdateModel.cs @@ -0,0 +1,22 @@ +using BotSharp.Abstraction.Tasks.Models; + +namespace BotSharp.OpenAPI.ViewModels.Agents; + +public class AgentTaskUpdateModel +{ + public string? Name { get; set; } + public string? Description { get; set; } + public string? Content { get; set; } + public bool Enabled { get; set; } + + public AgentTask ToAgentTask() + { + return new AgentTask + { + Name = Name, + Description = Description, + Content = Content, + Enabled = Enabled + }; + } +} diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskViewModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskViewModel.cs index 0e69a25b..2fc06dc3 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskViewModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentTaskViewModel.cs @@ -28,8 +28,8 @@ public class AgentTaskViewModel Description = task.Description, Content = task.Content, Enabled = task.Enabled, - AgentId = task.Agent.Id, - AgentName = task.Agent.Name, + AgentId = task.AgentId, + AgentName = task.Agent?.Name, 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 6f3b6d94..ac3dd97e 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.AgentTask.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.AgentTask.cs @@ -18,6 +18,11 @@ public partial class MongoRepository filters.Add(builder.Eq(x => x.AgentId, filter.AgentId)); } + if (filter.Enabled.HasValue) + { + filters.Add(builder.Eq(x => x.Enabled, filter.Enabled.Value)); + } + var filterDef = builder.And(filters); var sortDef = Builders.Sort.Descending(x => x.CreatedTime); var totalTasks = _dc.AgentTasks.CountDocuments(filterDef); @@ -89,6 +94,40 @@ public partial class MongoRepository _dc.AgentTasks.InsertOne(taskDoc); } + public void UpdateAgentTask(AgentTask task, AgentTaskField field) + { + if (task == null || string.IsNullOrEmpty(task.Id)) return; + + var filter = Builders.Filter.Eq(x => x.Id, task.Id); + var taskDoc = _dc.AgentTasks.Find(filter).FirstOrDefault(); + if (taskDoc == null) return; + + switch (field) + { + case AgentTaskField.Name: + taskDoc.Name = task.Name; + break; + case AgentTaskField.Description: + taskDoc.Description = task.Description; + break; + case AgentTaskField.Enabled: + taskDoc.Enabled = task.Enabled; + break; + case AgentTaskField.Content: + taskDoc.Content = task.Content; + break; + case AgentTaskField.All: + taskDoc.Name = task.Name; + taskDoc.Description = task.Description; + taskDoc.Enabled = task.Enabled; + taskDoc.Content = task.Content; + break; + } + + taskDoc.UpdatedTime = DateTime.UtcNow; + _dc.AgentTasks.ReplaceOne(filter, taskDoc); + } + public bool DeleteAgentTask(string agentId, string taskId) { if (string.IsNullOrEmpty(taskId)) return false;