From d05fa40bb7cc360045e0ccb7653d209c81943464 Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Mon, 28 Apr 2025 14:53:32 -0500 Subject: [PATCH] add agent links --- .../Agents/Enums/AgentField.cs | 1 + .../Agents/Models/Agent.cs | 14 ++++ .../Agents/Models/AgentLink.cs | 17 +++++ .../Agents/Models/AgentPromptBase.cs | 23 +++++++ .../Agents/Models/AgentTemplate.cs | 14 ++-- .../Templating/ITemplateRender.cs | 19 +++++- .../BotSharp.Core/Agents/AgentPlugin.cs | 2 +- .../Services/AgentService.CreateAgent.cs | 20 ++++++ .../Services/AgentService.RefreshAgents.cs | 2 + .../Agents/Services/AgentService.Rendering.cs | 23 +++++++ .../Services/AgentService.UpdateAgent.cs | 6 +- .../Conversations/ConversationPlugin.cs | 2 +- .../FileRepository/FileRepository.Agent.cs | 23 +++++++ .../FileRepository/FileRepository.cs | 27 +++++++- .../Templating/TemplateRender.cs | 65 +++++++++++++++++-- .../instructions/instruction.liquid | 2 +- .../Agents/Request/AgentCreationModel.cs | 3 + .../Agents/Request/AgentUpdateModel.cs | 6 ++ .../ViewModels/Agents/View/AgentViewModel.cs | 2 + .../Collections/AgentDocument.cs | 1 + .../Models/AgentLinkMongoElement.cs | 28 ++++++++ .../Repository/MongoRepository.Agent.cs | 19 ++++++ 22 files changed, 298 insertions(+), 21 deletions(-) create mode 100644 src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentLink.cs create mode 100644 src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentPromptBase.cs create mode 100644 src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentLinkMongoElement.cs diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs index 0cab0dfb..ebdffe39 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Enums/AgentField.cs @@ -16,6 +16,7 @@ public enum AgentField Instruction, Function, Template, + Link, Response, Sample, LlmConfig, diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs index 81cb7a3b..e43892fa 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/Agent.cs @@ -46,6 +46,12 @@ public class Agent [JsonIgnore] public List Templates { get; set; } = new(); + /// + /// Links that can be filled into parent prompt + /// + [JsonIgnore] + public List Links { get; set; } = new(); + /// /// Agent tasks /// @@ -168,6 +174,8 @@ public class Agent Functions = agent.Functions, Responses = agent.Responses, Samples = agent.Samples, + Templates = agent.Templates, + Links = agent.Links, Utilities = agent.Utilities, McpTools = agent.McpTools, Knowledges = agent.Knowledges, @@ -204,6 +212,12 @@ public class Agent return this; } + public Agent SetLinks(List links) + { + Links = links ?? []; + return this; + } + public Agent SetTasks(List tasks) { Tasks = tasks ?? []; diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentLink.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentLink.cs new file mode 100644 index 00000000..c1bdbfae --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentLink.cs @@ -0,0 +1,17 @@ +namespace BotSharp.Abstraction.Agents.Models; + +public class AgentLink : AgentPromptBase +{ + public AgentLink() : base() + { + } + + public AgentLink(string name, string content) : base(name, content) + { + } + + public override string ToString() + { + return base.ToString(); + } +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentPromptBase.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentPromptBase.cs new file mode 100644 index 00000000..c199a773 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentPromptBase.cs @@ -0,0 +1,23 @@ +namespace BotSharp.Abstraction.Agents.Models; + +public class AgentPromptBase +{ + public string Name { get; set; } + public string Content { get; set; } + + public AgentPromptBase() + { + + } + + public AgentPromptBase(string name, string content) + { + Name = name; + Content = content; + } + + public override string ToString() + { + return Name; + } +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentTemplate.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentTemplate.cs index 9591934f..f9225baa 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentTemplate.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentTemplate.cs @@ -1,23 +1,17 @@ namespace BotSharp.Abstraction.Agents.Models; -public class AgentTemplate +public class AgentTemplate : AgentPromptBase { - public string Name { get; set; } - public string Content { get; set; } - - public AgentTemplate() + public AgentTemplate() : base() { - } - public AgentTemplate(string name, string content) + public AgentTemplate(string name, string content) : base(name, content) { - Name = name; - Content = content; } public override string ToString() { - return Name; + return base.ToString(); } } diff --git a/src/Infrastructure/BotSharp.Abstraction/Templating/ITemplateRender.cs b/src/Infrastructure/BotSharp.Abstraction/Templating/ITemplateRender.cs index 82eff1c1..77e942dd 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Templating/ITemplateRender.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Templating/ITemplateRender.cs @@ -3,5 +3,22 @@ namespace BotSharp.Abstraction.Templating; public interface ITemplateRender { string Render(string template, Dictionary dict); - void Register(Type type); + + /// + /// Register tag + /// + /// + /// A dictionary whose key is identifier and value is its content to render + /// + /// + bool RegisterTag(string tag, Dictionary content, Dictionary? data = null); + + /// + /// Register tags + /// + /// A dictionary whose key is tag and value is its identifier and content to render + /// + /// + bool RegisterTags(Dictionary> tags, Dictionary? data = null); + void RegisterType(Type type); } diff --git a/src/Infrastructure/BotSharp.Core/Agents/AgentPlugin.cs b/src/Infrastructure/BotSharp.Core/Agents/AgentPlugin.cs index e6998fe4..41e13da4 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/AgentPlugin.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/AgentPlugin.cs @@ -45,7 +45,7 @@ public class AgentPlugin : IBotSharpPlugin { var settingService = provider.GetRequiredService(); var render = provider.GetRequiredService(); - render.Register(typeof(AgentSettings)); + render.RegisterType(typeof(AgentSettings)); return settingService.Bind("Agent"); }); } diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs index 5becbec6..9984c222 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.CreateAgent.cs @@ -111,6 +111,26 @@ public partial class AgentService return templates; } + private List GetLinksFromFile(string fileDir) + { + var links = new List(); + var linkDir = Path.Combine(fileDir, "links"); + if (!Directory.Exists(linkDir)) return links; + + foreach (var file in Directory.GetFiles(linkDir)) + { + var extension = Path.GetExtension(file).Substring(1); + if (extension.IsEqualTo(_agentSettings.TemplateFormat)) + { + var name = Path.GetFileNameWithoutExtension(file); + var content = File.ReadAllText(file); + links.Add(new AgentLink(name, content)); + } + } + + return links; + } + private List GetFunctionsFromFile(string fileDir) { var functions = new List(); diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.RefreshAgents.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.RefreshAgents.cs index c9b3c90c..b659083f 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.RefreshAgents.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.RefreshAgents.cs @@ -52,10 +52,12 @@ public partial class AgentService var functions = GetFunctionsFromFile(dir); var responses = GetResponsesFromFile(dir); var templates = GetTemplatesFromFile(dir); + var links = GetLinksFromFile(dir); var samples = GetSamplesFromFile(dir); agent.SetInstruction(defaultInstruction) .SetChannelInstructions(channelInstructions) .SetTemplates(templates) + .SetLinks(links) .SetFunctions(functions) .SetResponses(responses) .SetSamples(samples); diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs index 288a7ca1..6e63c86b 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs @@ -22,6 +22,7 @@ public partial class AgentService agent.TemplateDict[t.Key] = t.Value; } + RenderAgentLinks(agent, agent.TemplateDict); var res = render.Render(string.Join("\r\n", instructions), agent.TemplateDict); return res; } @@ -136,4 +137,26 @@ public partial class AgentService return content; } + + private void RenderAgentLinks(Agent agent, Dictionary dict) + { + var render = _services.GetRequiredService(); + + var links = new Dictionary(); + agent.Links ??= []; + + foreach (var link in agent.Links) + { + if (string.IsNullOrWhiteSpace(link.Name) + || string.IsNullOrWhiteSpace(link.Content)) + { + continue; + } + + links[link.Name] = link.Content; + } + + render.RegisterTag("link", links, dict); + return; + } } \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs index 29caa972..9b15e777 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.UpdateAgent.cs @@ -38,6 +38,7 @@ public partial class AgentService record.ChannelInstructions = agent.ChannelInstructions ?? []; record.Functions = agent.Functions ?? []; record.Templates = agent.Templates ?? []; + record.Links = agent.Links ?? []; record.Responses = agent.Responses ?? []; record.Samples = agent.Samples ?? []; record.Utilities = agent.Utilities ?? []; @@ -105,6 +106,7 @@ public partial class AgentService .SetInstruction(foundAgent.Instruction) .SetChannelInstructions(foundAgent.ChannelInstructions) .SetTemplates(foundAgent.Templates) + .SetLinks(foundAgent.Links) .SetFunctions(foundAgent.Functions) .SetResponses(foundAgent.Responses) .SetSamples(foundAgent.Samples) @@ -196,10 +198,12 @@ public partial class AgentService var functions = GetFunctionsFromFile(dir); var responses = GetResponsesFromFile(dir); var templates = GetTemplatesFromFile(dir); + var links = GetLinksFromFile(dir); var samples = GetSamplesFromFile(dir); return agent.SetInstruction(defaultInstruction) .SetChannelInstructions(channelInstructions) - .SetTemplates(templates) + .SetTemplates(templates) + .SetLinks(links) .SetFunctions(functions) .SetResponses(responses) .SetSamples(samples); diff --git a/src/Infrastructure/BotSharp.Core/Conversations/ConversationPlugin.cs b/src/Infrastructure/BotSharp.Core/Conversations/ConversationPlugin.cs index 09936dec..13ee1de6 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/ConversationPlugin.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/ConversationPlugin.cs @@ -31,7 +31,7 @@ public class ConversationPlugin : IBotSharpPlugin { var settingService = provider.GetRequiredService(); var render = provider.GetRequiredService(); - render.Register(typeof(ConversationSetting)); + render.RegisterType(typeof(ConversationSetting)); return settingService.Bind("Conversation"); }); diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs index 930eb13d..5219a0b0 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Agent.cs @@ -51,6 +51,9 @@ namespace BotSharp.Core.Repository case AgentField.Template: UpdateAgentTemplates(agent.Id, agent.Templates); break; + case AgentField.Link: + UpdateAgentLinks(agent.Id, agent.Links); + break; case AgentField.Response: UpdateAgentResponses(agent.Id, agent.Responses); break; @@ -325,6 +328,23 @@ namespace BotSharp.Core.Repository } } + private void UpdateAgentLinks(string agentId, List links) + { + if (links == null) return; + + var (agent, agentFile) = GetAgentFromFile(agentId); + if (agent == null) return; + + var linkDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, AGENT_LINKS_FOLDER); + DeleteBeforeCreateDirectory(linkDir); + + foreach (var link in links) + { + var file = Path.Combine(linkDir, $"{link.Name}.{_agentSettings.TemplateFormat}"); + File.WriteAllText(file, link.Content); + } + } + private void UpdateAgentResponses(string agentId, List responses) { if (responses == null) return; @@ -404,6 +424,7 @@ namespace BotSharp.Core.Repository UpdateAgentInstructions(inputAgent.Id, inputAgent.Instruction, inputAgent.ChannelInstructions); UpdateAgentResponses(inputAgent.Id, inputAgent.Responses); UpdateAgentTemplates(inputAgent.Id, inputAgent.Templates); + UpdateAgentLinks(inputAgent.Id, inputAgent.Links); UpdateAgentFunctions(inputAgent.Id, inputAgent.Functions); UpdateAgentSamples(inputAgent.Id, inputAgent.Samples); } @@ -447,11 +468,13 @@ namespace BotSharp.Core.Repository var functions = FetchFunctions(dir); var samples = FetchSamples(dir); var templates = FetchTemplates(dir); + var links = FetchLinks(dir); var responses = FetchResponses(dir); return record.SetInstruction(defaultInstruction) .SetChannelInstructions(channelInstructions) .SetFunctions(functions) .SetTemplates(templates) + .SetLinks(links) .SetSamples(samples) .SetResponses(responses); } diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.cs index f26e8bc0..eecf9b45 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.cs @@ -24,6 +24,7 @@ public partial class FileRepository : IBotSharpRepository private const string AGENT_INSTRUCTIONS_FOLDER = "instructions"; private const string AGENT_FUNCTIONS_FOLDER = "functions"; private const string AGENT_TEMPLATES_FOLDER = "templates"; + private const string AGENT_LINKS_FOLDER = "links"; private const string AGENT_RESPONSES_FOLDER = "responses"; private const string AGENT_TASKS_FOLDER = "tasks"; private const string AGENT_TASK_PREFIX = "#metadata"; @@ -228,6 +229,7 @@ public partial class FileRepository : IBotSharpRepository .SetChannelInstructions(channelInstructions) .SetFunctions(FetchFunctions(d)) .SetTemplates(FetchTemplates(d)) + .SetLinks(FetchLinks(d)) .SetResponses(FetchResponses(d)) .SetSamples(FetchSamples(d)); _agents.Add(agent); @@ -386,7 +388,7 @@ public partial class FileRepository : IBotSharpRepository foreach (var file in Directory.GetFiles(templateDir)) { - var fileName = file.Split(Path.DirectorySeparatorChar).Last(); + var fileName = Path.GetFileName(file); var splitIdx = fileName.LastIndexOf("."); var name = fileName.Substring(0, splitIdx); var extension = fileName.Substring(splitIdx + 1); @@ -400,6 +402,29 @@ public partial class FileRepository : IBotSharpRepository return templates; } + private List FetchLinks(string fileDir) + { + var links = new List(); + var linkDir = Path.Combine(fileDir, AGENT_LINKS_FOLDER); + + if (!Directory.Exists(linkDir)) return links; + + foreach (var file in Directory.GetFiles(linkDir)) + { + var fileName = Path.GetFileName(file); + var splitIdx = fileName.LastIndexOf("."); + var name = fileName.Substring(0, splitIdx); + var extension = fileName.Substring(splitIdx + 1); + if (extension.Equals(_agentSettings.TemplateFormat, StringComparison.OrdinalIgnoreCase)) + { + var content = File.ReadAllText(file); + links.Add(new AgentLink(name, content)); + } + + } + return links; + } + private List FetchTasks(string fileDir) { var tasks = new List(); diff --git a/src/Infrastructure/BotSharp.Core/Templating/TemplateRender.cs b/src/Infrastructure/BotSharp.Core/Templating/TemplateRender.cs index c16a8c4b..ace11c41 100644 --- a/src/Infrastructure/BotSharp.Core/Templating/TemplateRender.cs +++ b/src/Infrastructure/BotSharp.Core/Templating/TemplateRender.cs @@ -3,6 +3,7 @@ using BotSharp.Abstraction.Routing.Models; using BotSharp.Abstraction.Templating; using BotSharp.Abstraction.Translation.Models; using Fluid; +using Fluid.Ast; using System.Collections; using System.Reflection; @@ -40,17 +41,71 @@ public class TemplateRender : ITemplateRender { var context = new TemplateContext(dict, _options); template = t.Render(context); - return template; } else { _logger.LogWarning(error); - return template; } + + return template; } + public bool RegisterTag(string tag, Dictionary content, Dictionary? data = null) + { + _parser.RegisterIdentifierTag(tag, (identifier, writer, encoder, context) => + { + if (content?.TryGetValue(identifier, out var value) == true) + { + var str = Render(value, data ?? []); + writer.Write(str); + } + else + { + writer.Write(string.Empty); + } + return Statement.Normal(); + }); - public void Register(Type type) + return true; + } + + public bool RegisterTags(Dictionary> tags, Dictionary? data = null) + { + if (tags.IsNullOrEmpty()) return false; + + foreach (var item in tags) + { + var tag = item.Key; + if (string.IsNullOrWhiteSpace(tag) + || item.Value.IsNullOrEmpty()) + { + continue; + } + + foreach (var prompt in item.Value) + { + _parser.RegisterIdentifierTag(tag, (identifier, writer, encoder, context) => + { + var found = item.Value.FirstOrDefault(x => x.Name.IsEqualTo(identifier)); + if (found != null) + { + var str = Render(found.Content, data ?? []); + writer.Write(str); + } + else + { + writer.Write(string.Empty); + } + + return Statement.Normal(); + }); + } + } + + return true; + } + + public void RegisterType(Type type) { if (type == null || IsStringType(type)) return; @@ -59,7 +114,7 @@ public class TemplateRender : ITemplateRender if (type.IsGenericType) { var genericType = type.GetGenericArguments()[0]; - Register(genericType); + RegisterType(genericType); } } else if (IsTrackToNextLevel(type)) @@ -68,7 +123,7 @@ public class TemplateRender : ITemplateRender var props = type.GetProperties(); foreach (var prop in props) { - Register(prop.PropertyType); + RegisterType(prop.PropertyType); } } } diff --git a/src/Infrastructure/BotSharp.Core/data/agents/01e2fc5c-2c89-4ec7-8470-7688608b496c/instructions/instruction.liquid b/src/Infrastructure/BotSharp.Core/data/agents/01e2fc5c-2c89-4ec7-8470-7688608b496c/instructions/instruction.liquid index d944594b..7401fe35 100644 --- a/src/Infrastructure/BotSharp.Core/data/agents/01e2fc5c-2c89-4ec7-8470-7688608b496c/instructions/instruction.liquid +++ b/src/Infrastructure/BotSharp.Core/data/agents/01e2fc5c-2c89-4ec7-8470-7688608b496c/instructions/instruction.liquid @@ -1 +1 @@ -You are a AI Assistant. You can answer user's question. +You are a AI Assistant. You can answer user's question. \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/Request/AgentCreationModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/Request/AgentCreationModel.cs index 8265ebe4..61aa89fd 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/Request/AgentCreationModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/Request/AgentCreationModel.cs @@ -24,6 +24,8 @@ public class AgentCreationModel /// public List Templates { get; set; } = new(); + public List Links { get; set; } = new(); + /// /// LLM callable function definition /// @@ -70,6 +72,7 @@ public class AgentCreationModel Instruction = Instruction, ChannelInstructions = ChannelInstructions, Templates = Templates, + Links = Links, Functions = Functions, Responses = Responses, Samples = Samples, diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/Request/AgentUpdateModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/Request/AgentUpdateModel.cs index b11a9db0..0e9b8ebb 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/Request/AgentUpdateModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/Request/AgentUpdateModel.cs @@ -25,6 +25,11 @@ public class AgentUpdateModel /// public List? Templates { get; set; } + /// + /// Links + /// + public List? Links { get; set; } + /// /// Samples /// @@ -105,6 +110,7 @@ public class AgentUpdateModel Instruction = Instruction ?? string.Empty, ChannelInstructions = ChannelInstructions ?? [], Templates = Templates ?? [], + Links = Links ?? [], Functions = Functions ?? [], Responses = Responses ?? [], Utilities = Utilities ?? [], diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/View/AgentViewModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/View/AgentViewModel.cs index 4fede545..6fe468d0 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/View/AgentViewModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/View/AgentViewModel.cs @@ -18,6 +18,7 @@ public class AgentViewModel [JsonPropertyName("channel_instructions")] public List ChannelInstructions { get; set; } public List Templates { get; set; } + public List Links { get; set; } public List Functions { get; set; } public List Responses { get; set; } public List Samples { get; set; } @@ -87,6 +88,7 @@ public class AgentViewModel Instruction = agent.Instruction, ChannelInstructions = agent.ChannelInstructions ?? [], Templates = agent.Templates ?? [], + Links = agent.Links ?? [], Functions = agent.Functions ?? [], Responses = agent.Responses ?? [], Samples = agent.Samples ?? [], diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs index 7ebded25..47e7d061 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/AgentDocument.cs @@ -15,6 +15,7 @@ public class AgentDocument : MongoBase public int? MaxMessageCount { get; set; } public List ChannelInstructions { get; set; } public List Templates { get; set; } + public List Links { get; set; } public List Functions { get; set; } public List Responses { get; set; } public List Samples { get; set; } diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentLinkMongoElement.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentLinkMongoElement.cs new file mode 100644 index 00000000..f618e03a --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentLinkMongoElement.cs @@ -0,0 +1,28 @@ +using BotSharp.Abstraction.Agents.Models; + +namespace BotSharp.Plugin.MongoStorage.Models; + +[BsonIgnoreExtraElements(Inherited = true)] +public class AgentLinkMongoElement +{ + public string Name { get; set; } = default!; + public string Content { get; set; } = default!; + + public static AgentLinkMongoElement ToMongoElement(AgentLink link) + { + return new AgentLinkMongoElement + { + Name = link.Name, + Content = link.Content + }; + } + + public static AgentLink ToDomainElement(AgentLinkMongoElement mongoLink) + { + return new AgentLink + { + Name = mongoLink.Name, + Content = mongoLink.Content + }; + } +} diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs index 6eda94ed..35cde7ee 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs @@ -52,6 +52,9 @@ public partial class MongoRepository case AgentField.Template: UpdateAgentTemplates(agent.Id, agent.Templates); break; + case AgentField.Link: + UpdateAgentLinks(agent.Id, agent.Links); + break; case AgentField.Response: UpdateAgentResponses(agent.Id, agent.Responses); break; @@ -237,6 +240,19 @@ public partial class MongoRepository _dc.Agents.UpdateOne(filter, update); } + private void UpdateAgentLinks(string agentId, List links) + { + if (links == null) return; + + var linksToUpdate = links.Select(t => AgentLinkMongoElement.ToMongoElement(t)).ToList(); + var filter = Builders.Filter.Eq(x => x.Id, agentId); + var update = Builders.Update + .Set(x => x.Links, linksToUpdate) + .Set(x => x.UpdatedTime, DateTime.UtcNow); + + _dc.Agents.UpdateOne(filter, update); + } + private void UpdateAgentResponses(string agentId, List responses) { if (responses == null || string.IsNullOrWhiteSpace(agentId)) return; @@ -356,6 +372,7 @@ public partial class MongoRepository .Set(x => x.Instruction, agent.Instruction) .Set(x => x.ChannelInstructions, agent.ChannelInstructions.Select(i => ChannelInstructionMongoElement.ToMongoElement(i)).ToList()) .Set(x => x.Templates, agent.Templates.Select(t => AgentTemplateMongoElement.ToMongoElement(t)).ToList()) + .Set(x => x.Links, agent.Links.Select(t => AgentLinkMongoElement.ToMongoElement(t)).ToList()) .Set(x => x.Functions, agent.Functions.Select(f => FunctionDefMongoElement.ToMongoElement(f)).ToList()) .Set(x => x.Responses, agent.Responses.Select(r => AgentResponseMongoElement.ToMongoElement(r)).ToList()) .Set(x => x.Samples, agent.Samples) @@ -538,6 +555,7 @@ public partial class MongoRepository LlmConfig = AgentLlmConfigMongoElement.ToMongoElement(x.LlmConfig), ChannelInstructions = x.ChannelInstructions?.Select(i => ChannelInstructionMongoElement.ToMongoElement(i))?.ToList() ?? [], Templates = x.Templates?.Select(t => AgentTemplateMongoElement.ToMongoElement(t))?.ToList() ?? [], + Links = x.Links?.Select(l => AgentLinkMongoElement.ToMongoElement(l))?.ToList() ?? [], Functions = x.Functions?.Select(f => FunctionDefMongoElement.ToMongoElement(f))?.ToList() ?? [], Responses = x.Responses?.Select(r => AgentResponseMongoElement.ToMongoElement(r))?.ToList() ?? [], RoutingRules = x.RoutingRules?.Select(r => RoutingRuleMongoElement.ToMongoElement(r))?.ToList() ?? [], @@ -634,6 +652,7 @@ public partial class MongoRepository LlmConfig = AgentLlmConfigMongoElement.ToDomainElement(agentDoc.LlmConfig), ChannelInstructions = agentDoc.ChannelInstructions?.Select(i => ChannelInstructionMongoElement.ToDomainElement(i))?.ToList() ?? [], Templates = agentDoc.Templates?.Select(t => AgentTemplateMongoElement.ToDomainElement(t))?.ToList() ?? [], + Links = agentDoc.Links?.Select(l => AgentLinkMongoElement.ToDomainElement(l))?.ToList() ?? [], Functions = agentDoc.Functions?.Select(f => FunctionDefMongoElement.ToDomainElement(f)).ToList() ?? [], Responses = agentDoc.Responses?.Select(r => AgentResponseMongoElement.ToDomainElement(r))?.ToList() ?? [], RoutingRules = agentDoc.RoutingRules?.Select(r => RoutingRuleMongoElement.ToDomainElement(agentDoc.Id, agentDoc.Name, r))?.ToList() ?? [],