diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs index 8e44a73d..567a3dac 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs @@ -84,7 +84,7 @@ public partial class AgentService private string FetchInstructionFromFile(string fileDir) { - var file = Path.Combine(fileDir, "instruction.liquid"); + var file = Path.Combine(fileDir, $"instruction.{_agentSettings.TemplateFormat}"); if (!File.Exists(file)) return null; var instruction = File.ReadAllText(file); @@ -100,7 +100,7 @@ public partial class AgentService var splits = fileName.ToLower().Split('.'); var name = splits[0]; var extension = splits[1]; - if (name != "instruction" && extension == "liquid") + if (name != "instruction" && extension == _agentSettings.TemplateFormat) { var content = File.ReadAllText(file); templates.Add(new AgentTemplate(name, content)); diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs index 323a0dec..6b613503 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.cs @@ -9,20 +9,20 @@ public partial class AgentService : IAgentService private readonly IBotSharpRepository _db; private readonly ILogger _logger; private readonly IUserIdentity _user; - private readonly AgentSettings _settings; + private readonly AgentSettings _agentSettings; private readonly JsonSerializerOptions _options; public AgentService(IServiceProvider services, IBotSharpRepository db, ILogger logger, IUserIdentity user, - AgentSettings settings) + AgentSettings agentSettings) { _services = services; _db = db; _logger = logger; _user = user; - _settings = settings; + _agentSettings = agentSettings; _options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, @@ -40,7 +40,7 @@ public partial class AgentService : IAgentService public string GetAgentDataDir(string agentId) { var dbSettings = _services.GetRequiredService(); - var dir = Path.Combine(dbSettings.FileRepository, _settings.DataDir, agentId); + var dir = Path.Combine(dbSettings.FileRepository, _agentSettings.DataDir, agentId); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); diff --git a/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs b/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs index db95814a..d8f6ef52 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs @@ -1,4 +1,3 @@ -using BotSharp.Abstraction.Agents.Enums; using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Repositories; using BotSharp.Abstraction.Routing.Models; @@ -72,77 +71,55 @@ public class BotSharpDbContext : Database, IBotSharpRepository } - - public void CreateNewConversation(Conversation conversation) - { - throw new NotImplementedException(); - } - - public List CreateRoutingItems(List routingItems) - { - throw new NotImplementedException(); - } - - public List CreateRoutingProfiles(List profiles) - { - throw new NotImplementedException(); - } - - public void CreateUser(User user) - { - throw new NotImplementedException(); - } - - public void DeleteRoutingItems() - { - throw new NotImplementedException(); - } - - public void DeleteRoutingProfiles() - { - throw new NotImplementedException(); - } - + #region Agent public Agent GetAgent(string agentId) { throw new NotImplementedException(); } + public void UpdateAgent(Agent agent, AgentField field) + { + throw new NotImplementedException(); + } + + public string GetAgentTemplate(string agentId, string templateName) + { + throw new NotImplementedException(); + } + public List GetAgentResponses(string agentId, string prefix, string intent) { throw new NotImplementedException(); } + #endregion + + + #region Conversation + public void CreateNewConversation(Conversation conversation) + { + throw new NotImplementedException(); + } public Conversation GetConversation(string conversationId) { throw new NotImplementedException(); } - public string GetConversationDialog(string conversationId) - { - throw new NotImplementedException(); - } - public List GetConversations(string userId) { throw new NotImplementedException(); } + public string GetConversationDialog(string conversationId) + { + throw new NotImplementedException(); + } + public List GetConversationStates(string conversationId) { throw new NotImplementedException(); } - public User GetUserByEmail(string email) - { - throw new NotImplementedException(); - } - - public void UpdateAgent(Agent agent, AgentField field) - { - throw new NotImplementedException(); - } - public void UpdateConversationDialog(string conversationId, string dialogs) { throw new NotImplementedException(); @@ -152,9 +129,41 @@ public class BotSharpDbContext : Database, IBotSharpRepository { throw new NotImplementedException(); } + #endregion - public string GetAgentTemplate(string agentId, string templateName) + + #region User + public User GetUserByEmail(string email) { throw new NotImplementedException(); } + + public void CreateUser(User user) + { + throw new NotImplementedException(); + } + #endregion + + + #region Routing + public List CreateRoutingItems(List routingItems) + { + throw new NotImplementedException(); + } + + public List CreateRoutingProfiles(List profiles) + { + throw new NotImplementedException(); + } + + public void DeleteRoutingItems() + { + throw new NotImplementedException(); + } + + public void DeleteRoutingProfiles() + { + throw new NotImplementedException(); + } + #endregion } diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository.cs index 99f03c59..8b45a8f0 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/FileRepository.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository.cs @@ -4,7 +4,10 @@ using FunctionDef = BotSharp.Abstraction.Functions.Models.FunctionDef; using BotSharp.Abstraction.Users.Models; using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Routing.Models; -using BotSharp.Abstraction.Agents.Enums; +using MongoDB.Driver; +using Microsoft.Extensions.Logging; +using System.Xml.Linq; +using static Tensorflow.TensorShapeProto.Types; namespace BotSharp.Core.Repository; @@ -211,9 +214,7 @@ public class FileRepository : IBotSharpRepository { foreach (var conversation in _conversations) { - var dir = Path.Combine(_dbSettings.FileRepository, - _conversationSettings.DataDir, - conversation.Id); + var dir = Path.Combine(_dbSettings.FileRepository, _conversationSettings.DataDir, conversation.Id); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); @@ -226,9 +227,7 @@ public class FileRepository : IBotSharpRepository { foreach (var agent in _agents) { - var dir = Path.Combine(_dbSettings.FileRepository, - _agentSettings.DataDir, - agent.Id); + var dir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agent.Id); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); @@ -241,9 +240,7 @@ public class FileRepository : IBotSharpRepository { foreach (var user in _users) { - var dir = Path.Combine(_dbSettings.FileRepository, - "users", - user.Id); + var dir = Path.Combine(_dbSettings.FileRepository, "users", user.Id); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); @@ -276,31 +273,176 @@ public class FileRepository : IBotSharpRepository #region Agent public void UpdateAgent(Agent agent, AgentField field) { - if (agent == null) return; + if (agent == null || string.IsNullOrEmpty(agent.Id)) return; - var dir = GetAgentDataDir(agent.Id); - - if (!string.IsNullOrEmpty(agent.Instruction)) + switch (field) { - var instructionFile = Path.Combine(dir, "instruction.liquid"); - File.WriteAllText(instructionFile, agent.Instruction); - } - - if (!agent.Functions.IsNullOrEmpty()) - { - var functionFile = Path.Combine(dir, "functions.json"); - var functions = new List(); - foreach (var function in agent.Functions) - { - var functionDef = JsonSerializer.Deserialize(function, _options); - functions.Add(JsonSerializer.Serialize(functionDef, _options)); - } - - var functionText = JsonSerializer.Serialize(functions, _options); - File.WriteAllText(functionFile, functionText); + case AgentField.Name: + UpdateAgentName(agent.Id, agent.Name); + break; + case AgentField.Description: + UpdateAgentDescription(agent.Id, agent.Description); + break; + case AgentField.IsPublic: + UpdateAgentIsPublic(agent.Id, agent.IsPublic); + break; + case AgentField.Instruction: + UpdateAgentInstruction(agent.Id, agent.Instruction); + break; + case AgentField.Function: + UpdateAgentFunctions(agent.Id, agent.Functions); + break; + case AgentField.Template: + UpdateAgentTemplates(agent.Id, agent.Templates); + break; + case AgentField.Response: + UpdateAgentResponses(agent.Id, agent.Responses); + break; + case AgentField.All: + UpdateAgentAllFields(agent); + break; + default: + break; } } + #region Update Agent Fields + private void UpdateAgentName(string agentId, string name) + { + if (string.IsNullOrEmpty(name)) return; + + var (agent, agentFile) = GetAgentFromFile(agentId); + if (agent == null) return; + + agent.Name = name; + agent.UpdatedDateTime = DateTime.UtcNow; + var json = JsonSerializer.Serialize(agent, _options); + File.WriteAllText(agentFile, json); + } + + private void UpdateAgentDescription(string agentId, string description) + { + if (string.IsNullOrEmpty(description)) return; + + var (agent, agentFile) = GetAgentFromFile(agentId); + if (agent == null) return; + + agent.Description = description; + agent.UpdatedDateTime = DateTime.UtcNow; + var json = JsonSerializer.Serialize(agent, _options); + File.WriteAllText(agentFile, json); + } + + private void UpdateAgentIsPublic(string agentId, bool isPublic) + { + var (agent, agentFile) = GetAgentFromFile(agentId); + if (agent == null) return; + + agent.IsPublic = isPublic; + agent.UpdatedDateTime = DateTime.UtcNow; + var json = JsonSerializer.Serialize(agent, _options); + File.WriteAllText(agentFile, json); + } + + private void UpdateAgentInstruction(string agentId, string instruction) + { + if (string.IsNullOrEmpty(instruction)) return; + + var (agent, agentFile) = GetAgentFromFile(agentId); + if (agent == null) return; + + var instructionFile = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, + agentId, $"instruction.{_agentSettings.TemplateFormat}"); + + File.WriteAllText(instructionFile, instruction); + } + + private void UpdateAgentFunctions(string agentId, List inputFunctions) + { + if (inputFunctions.IsNullOrEmpty()) return; + + var (agent, agentFile) = GetAgentFromFile(agentId); + if (agent == null) return; + + var functionFile = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, + agentId, "functions.json"); + + var functions = new List(); + foreach (var function in inputFunctions) + { + var functionDef = JsonSerializer.Deserialize(function, _options); + functions.Add(JsonSerializer.Serialize(functionDef, _options)); + } + + var functionText = JsonSerializer.Serialize(functions, _options); + File.WriteAllText(functionFile, functionText); + } + + private void UpdateAgentTemplates(string agentId, List templates) + { + if (templates.IsNullOrEmpty()) return; + + var (agent, agentFile) = GetAgentFromFile(agentId); + if (agent == null) return; + + var baseDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId); + + foreach (var file in Directory.GetFiles(baseDir)) + { + var fileName = file.Split(Path.DirectorySeparatorChar).Last(); + var splits = fileName.ToLower().Split('.'); + var name = splits[0]; + var extension = splits[1]; + if (name != "instruction" && extension == _agentSettings.TemplateFormat) + { + File.Delete(file); + } + } + + foreach (var template in templates) + { + var file = Path.Combine(baseDir, $"{template.Name}.{_agentSettings.TemplateFormat}"); + File.WriteAllText(file, template.Content); + } + } + + private void UpdateAgentResponses(string agentId, List responses) + { + if (responses.IsNullOrEmpty()) return; + + var (agent, agentFile) = GetAgentFromFile(agentId); + if (agent == null) return; + + var baseDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId); + var responseDir = Path.Combine(baseDir, "responses"); + if (!Directory.Exists(responseDir)) + { + Directory.CreateDirectory(responseDir); + } + + foreach (var file in Directory.GetFiles(responseDir)) + { + File.Delete(file); + } + + for (int i = 0; i < responses.Count; i++) + { + var response = responses[i]; + var fileName = $"{response.Prefix}.{response.Intent}.{i}.{_agentSettings.TemplateFormat}"; + var file = Path.Combine(responseDir, fileName); + File.WriteAllText(file, response.Content); + } + } + + private void UpdateAgentAllFields(Agent inputAgent) + { + var (agent, agentFile) = GetAgentFromFile(inputAgent.Id); + if (agent == null) return; + + + } + #endregion + #if !DEBUG [MemoryCache(10 * 60)] #endif @@ -352,7 +494,7 @@ public class FileRepository : IBotSharpRepository var splits = fileName.ToLower().Split('.'); var name = splits[0]; var extension = splits[1]; - if (name == lowerTemplateName && extension == "liquid") + if (name == lowerTemplateName && extension == _agentSettings.TemplateFormat) { return File.ReadAllText(file); } @@ -556,14 +698,25 @@ public class FileRepository : IBotSharpRepository var dir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId); if (!Directory.Exists(dir)) { - Directory.CreateDirectory(dir); + dir = string.Empty; } return dir; } + private (Agent?, string) GetAgentFromFile(string agentId) + { + var dir = GetAgentDataDir(agentId); + var agentFile = Path.Combine(dir, "agent.json"); + if (!File.Exists(agentFile)) return (null, string.Empty); + + var json = File.ReadAllText(agentFile); + var agent = JsonSerializer.Deserialize(json, _options); + return (agent, agentFile); + } + private string FetchInstruction(string fileDir) { - var file = Path.Combine(fileDir, "instruction.liquid"); + var file = Path.Combine(fileDir, $"instruction.{_agentSettings.TemplateFormat}"); if (!File.Exists(file)) return string.Empty; var instruction = File.ReadAllText(file); @@ -591,7 +744,7 @@ public class FileRepository : IBotSharpRepository var splits = fileName.ToLower().Split('.'); var name = splits[0]; var extension = splits[1]; - if (name != "instruction" && extension == "liquid") + if (name != "instruction" && extension == _agentSettings.TemplateFormat) { var content = File.ReadAllText(file); templates.Add(new AgentTemplate(name, content));