diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs index 9f119bb1..6af6f4b0 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs @@ -18,6 +18,7 @@ public interface IAgentService Task GetAgent(string id); Task DeleteAgent(string id); Task UpdateAgent(Agent agent); + Task UpdateAgentFromFile(string id); string GetDataDir(); string GetAgentDataDir(string agentId); } diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs index b942d7ea..0cd24632 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs @@ -29,7 +29,7 @@ public partial class AgentService var dbSettings = _services.GetRequiredService(); var agentSettings = _services.GetRequiredService(); var filePath = Path.Combine(dbSettings.FileRepository, agentSettings.DataDir); - var foundAgent = FetchAgentInfoFromFile(agent.Name, filePath); + var foundAgent = FetchAgentFileByName(agent.Name, filePath); if (foundAgent != null) { @@ -62,14 +62,7 @@ public partial class AgentService return agentRecord; } - private JsonSerializerOptions _options = new JsonSerializerOptions - { - PropertyNameCaseInsensitive = true, - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - WriteIndented = true - }; - - private Agent FetchAgentInfoFromFile(string agentName, string filePath) + private Agent FetchAgentFileByName(string agentName, string filePath) { foreach (var dir in Directory.GetDirectories(filePath)) { diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs index 6fe9cd48..55a60ad5 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs @@ -27,6 +27,9 @@ public partial class AgentService if (!string.IsNullOrEmpty(agent.Instruction)) record.Instruction = agent.Instruction; + if (!agent.Templates.IsNullOrEmpty()) + record.Templates = agent.Templates; + if (!agent.Functions.IsNullOrEmpty()) record.Functions = agent.Functions; @@ -36,4 +39,57 @@ public partial class AgentService db.UpdateAgent(record); await Task.CompletedTask; } + + public async Task UpdateAgentFromFile(string id) + { + var db = _services.GetRequiredService(); + var agent = db.Agents?.FirstOrDefault(x => x.Id == id); + + if (agent == null) return; + + var dbSettings = _services.GetRequiredService(); + var agentSettings = _services.GetRequiredService(); + var filePath = Path.Combine(dbSettings.FileRepository, agentSettings.DataDir); + + var clonedAgent = Agent.Clone(agent); + var foundAgent = FetchAgentFileById(agent.Id, filePath); + if (foundAgent != null) + { + clonedAgent.SetId(foundAgent.Id) + .SetName(foundAgent.Name) + .SetDescription(foundAgent.Description) + .SetIsPublic(foundAgent.IsPublic) + .SetInstruction(foundAgent.Instruction) + .SetTemplates(foundAgent.Templates) + .SetFunctions(foundAgent.Functions) + .SetResponses(foundAgent.Responses); + + db.UpdateAgent(clonedAgent); + } + + + await Task.CompletedTask; + } + + private Agent FetchAgentFileById(string agentId, string filePath) + { + foreach (var dir in Directory.GetDirectories(filePath)) + { + var agentJson = File.ReadAllText(Path.Combine(dir, "agent.json")); + var agent = JsonSerializer.Deserialize(agentJson, _options); + if (agent != null && agent.Id == agentId) + { + var functions = FetchFunctionsFromFile(dir); + var instruction = FetchInstructionFromFile(dir); + var responses = FetchResponsesFromFile(dir); + var templates = FetchTemplatesFromFile(dir); + return agent.SetInstruction(instruction) + .SetTemplates(templates) + .SetFunctions(functions) + .SetResponses(responses); + } + } + + return null; + } } diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs index 6e686bab..37d45601 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs @@ -10,6 +10,7 @@ public partial class AgentService : IAgentService private readonly ILogger _logger; private readonly IUserIdentity _user; private readonly AgentSettings _settings; + private readonly JsonSerializerOptions _options; public AgentService(IServiceProvider services, ILogger logger, @@ -20,6 +21,12 @@ public partial class AgentService : IAgentService _logger = logger; _user = user; _settings = settings; + _options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + WriteIndented = true + }; } public string GetDataDir() diff --git a/src/Infrastructure/BotSharp.Core/Routing/Services/RoutingService.Create.cs b/src/Infrastructure/BotSharp.Core/Routing/Services/RoutingService.Create.cs new file mode 100644 index 00000000..21d0f7e5 --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/Routing/Services/RoutingService.Create.cs @@ -0,0 +1,66 @@ +using BotSharp.Abstraction.Repositories; +using BotSharp.Abstraction.Routing.Models; +using System.IO; + +namespace BotSharp.Core.Routing.Services; + +public partial class RoutingService +{ + public async Task> CreateRoutingItems(List routingItems) + { + var db = _services.GetRequiredService(); + var items = FetchRoutingItemsFromFile(); + + if (items.IsNullOrEmpty()) + { + items = routingItems?.ToList() ?? new List(); + } + + var savedItems = db.CreateRoutingItems(items); + return await Task.FromResult(savedItems.ToList()); + } + + public async Task> CreateRoutingProfiles(List routingProfiles) + { + var db = _services.GetRequiredService(); + var profiles = FetchRoutingProfilesFromFile(); + + if (profiles.IsNullOrEmpty()) + { + profiles = routingProfiles?.ToList() ?? new List(); + } + + var savedProfiles = db.CreateRoutingProfiles(profiles); + return await Task.FromResult(savedProfiles.ToList()); + } + + private List FetchRoutingItemsFromFile() + { + var routingItems = new List(); + var dbSettings = _services.GetRequiredService(); + var agentSettings = _services.GetRequiredService(); + var filePath = Path.Combine(dbSettings.FileRepository, agentSettings.DataDir, "route.json"); + + if (File.Exists(filePath)) + { + routingItems = JsonSerializer.Deserialize>(File.ReadAllText(filePath), _options); + } + + return routingItems ?? new List(); + } + + private List FetchRoutingProfilesFromFile() + { + var routingProfiles = new List(); + var dbSettings = _services.GetRequiredService(); + var agentSettings = _services.GetRequiredService(); + var filePath = Path.Combine(dbSettings.FileRepository, agentSettings.DataDir, "routing-profile.json"); + + if (File.Exists(filePath)) + { + routingProfiles = JsonSerializer.Deserialize>(File.ReadAllText(filePath), _options); + } + + return routingProfiles ?? new List(); + } +} diff --git a/src/Infrastructure/BotSharp.Core/Routing/Services/RoutingService.Delete.cs b/src/Infrastructure/BotSharp.Core/Routing/Services/RoutingService.Delete.cs new file mode 100644 index 00000000..b61c3e91 --- /dev/null +++ b/src/Infrastructure/BotSharp.Core/Routing/Services/RoutingService.Delete.cs @@ -0,0 +1,20 @@ +using BotSharp.Abstraction.Repositories; + +namespace BotSharp.Core.Routing.Services; + +public partial class RoutingService +{ + public async Task DeleteRoutingItems() + { + var db = _services.GetRequiredService(); + db.DeleteRoutingItems(); + await Task.CompletedTask; + } + + public async Task DeleteRoutingProfiles() + { + var db = _services.GetRequiredService(); + db.DeleteRoutingProfiles(); + await Task.CompletedTask; + } +} diff --git a/src/Infrastructure/BotSharp.Core/Routing/Services/RoutingService.cs b/src/Infrastructure/BotSharp.Core/Routing/Services/RoutingService.cs index 70a74a87..dc34cc17 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Services/RoutingService.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Services/RoutingService.cs @@ -1,45 +1,23 @@ using BotSharp.Abstraction.Repositories; -using BotSharp.Abstraction.Repositories.Records; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Models; +using System.IO; namespace BotSharp.Core.Routing.Services; -public class RoutingService : IRoutingService +public partial class RoutingService : IRoutingService { private readonly IServiceProvider _services; + private readonly JsonSerializerOptions _options; public RoutingService(IServiceProvider service) { _services = service; - } - public async Task> CreateRoutingItems(List routingItems) - { - var db = _services.GetRequiredService(); - var items = routingItems?.ToList() ?? new List(); - var savedItems = db.CreateRoutingItems(items); - return await Task.FromResult(savedItems.ToList()); - } - - public async Task> CreateRoutingProfiles(List routingProfiles) - { - var db = _services.GetRequiredService(); - var profiles = routingProfiles?.ToList() ?? new List(); - var savedProfiles = db.CreateRoutingProfiles(profiles); - return await Task.FromResult(savedProfiles.ToList()); - } - - public async Task DeleteRoutingItems() - { - var db = _services.GetRequiredService(); - db.DeleteRoutingItems(); - await Task.CompletedTask; - } - - public async Task DeleteRoutingProfiles() - { - var db = _services.GetRequiredService(); - db.DeleteRoutingProfiles(); - await Task.CompletedTask; + _options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + WriteIndented = true + }; } } diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs index fb19ac5a..176d02dc 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs @@ -29,6 +29,12 @@ public class AgentController : ControllerBase, IApiAdapter await _agentService.UpdateAgent(model); } + [HttpPut("/agent/file/{agentId}")] + public async Task UpdateAgentFromFile([FromRoute] string agentId) + { + await _agentService.UpdateAgentFromFile(agentId); + } + [HttpGet("/agents")] public async Task> GetAgents() { diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs index 228d926b..c42ec29d 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs @@ -379,6 +379,7 @@ public class MongoRepository : IBotSharpRepository Name = agent.Name, Description = agent.Description, Instruction = agent.Instruction, + Templates = agent.Templates, Functions = agent.Functions, Responses = agent.Responses, IsPublic = agent.IsPublic, @@ -391,12 +392,13 @@ public class MongoRepository : IBotSharpRepository .Set(x => x.Name, agent.Name) .Set(x => x.Description, agent.Description) .Set(x => x.Instruction, agent.Instruction) + .Set(x => x.Templates, agent.Templates) .Set(x => x.Functions, agent.Functions) .Set(x => x.Responses, agent.Responses) .Set(x => x.IsPublic, agent.IsPublic) .Set(x => x.UpdatedTime, agent.UpdatedDateTime); - _dc.Agents.UpdateOne(filter, update, _options); + _dc.Agents.UpdateOne(filter, update); } public void DeleteRoutingItems()