From 28d4f4e9baccb976134a731e6ba30d4232a4a130 Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Tue, 27 May 2025 15:23:37 -0500 Subject: [PATCH 01/10] add utility visibility expression --- .../Agents/IAgentService.cs | 2 + .../Agents/Models/AgentUtility.cs | 4 ++ .../Agents/Hooks/BasicAgentHook.cs | 38 ++++++++++++------- .../Agents/Services/AgentService.LoadAgent.cs | 6 ++- .../Agents/Services/AgentService.Rendering.cs | 17 +++++++++ .../Models/AgentUtilityMongoElement.cs | 3 ++ .../Core/TestAgentService.cs | 6 +++ 7 files changed, 61 insertions(+), 15 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs index 45fd3251..b50be071 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs @@ -36,6 +36,8 @@ public interface IAgentService FunctionParametersDef? RenderFunctionProperty(Agent agent, FunctionDef def); + bool RenderUtility(Agent agent, AgentUtility utility); + /// /// Get agent detail without trigger any hook. /// diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentUtility.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentUtility.cs index ce39c568..1d426600 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentUtility.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentUtility.cs @@ -4,6 +4,10 @@ public class AgentUtility { public string Name { get; set; } public bool Disabled { get; set; } + + [JsonPropertyName("visibility_expression")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? VisibilityExpression { get; set; } public IEnumerable Functions { get; set; } = []; public IEnumerable Templates { get; set; } = []; diff --git a/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs b/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs index 10fa376c..03e7bb68 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs @@ -19,9 +19,9 @@ public class BasicAgentHook : AgentHookBase var isConvMode = conv.IsConversationMode(); if (!isConvMode) return; + agent.Utilities ??= []; agent.SecondaryFunctions ??= []; agent.SecondaryInstructions ??= []; - agent.Utilities ??= []; var (functions, templates) = GetUtilityContent(agent); @@ -34,7 +34,7 @@ public class BasicAgentHook : AgentHookBase private (IEnumerable, IEnumerable) GetUtilityContent(Agent agent) { var db = _services.GetRequiredService(); - var (functionNames, templateNames) = GetUniqueContent(agent.Utilities); + var (functionNames, templateNames) = FilterUtilityContent(agent.Utilities, agent); if (agent.MergeUtility) { @@ -43,7 +43,7 @@ public class BasicAgentHook : AgentHookBase if (!string.IsNullOrEmpty(entryAgentId)) { var entryAgent = db.GetAgent(entryAgentId, basicsOnly: true); - var (fns, tps) = GetUniqueContent(entryAgent?.Utilities); + var (fns, tps) = FilterUtilityContent(entryAgent?.Utilities, agent); functionNames = functionNames.Concat(fns).Distinct().ToList(); templateNames = templateNames.Concat(tps).Distinct().ToList(); } @@ -55,22 +55,34 @@ public class BasicAgentHook : AgentHookBase return (functions, templates); } - private (IEnumerable, IEnumerable) GetUniqueContent(IEnumerable? utilities) + private (IEnumerable, IEnumerable) FilterUtilityContent(IEnumerable? utilities, Agent agent) { if (utilities.IsNullOrEmpty()) { return ([], []); } - utilities = utilities?.Where(x => !string.IsNullOrEmpty(x.Name) && !x.Disabled)?.ToList() ?? []; - var functionNames = utilities.SelectMany(x => x.Functions) - .Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX)) - .Select(x => x.Name) - .Distinct().ToList(); - var templateNames = utilities.SelectMany(x => x.Templates) - .Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX)) - .Select(x => x.Name) - .Distinct().ToList(); + var agentService = _services.GetRequiredService(); + var innerUtilities = utilities!.Where(x => + { + var isVisible = !string.IsNullOrEmpty(x.Name) && !x.Disabled; + if (!isVisible) + { + return isVisible; + } + + isVisible = agentService.RenderUtility(agent, x); + return isVisible; + }).ToList(); + + var functionNames = innerUtilities.SelectMany(x => x.Functions) + .Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX)) + .Select(x => x.Name) + .Distinct().ToList(); + var templateNames = innerUtilities.SelectMany(x => x.Templates) + .Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX)) + .Select(x => x.Name) + .Distinct().ToList(); return (functionNames, templateNames); } diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs index 7fbfffdc..a15b2907 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.LoadAgent.cs @@ -1,4 +1,3 @@ -using BotSharp.Abstraction.Infrastructures; using BotSharp.Abstraction.Routing.Models; using System.Collections.Concurrent; @@ -18,12 +17,15 @@ public partial class AgentService var agent = await GetAgent(id); if (agent == null) return null; + agent.TemplateDict = []; + agent.SecondaryInstructions = []; + agent.SecondaryFunctions = []; + await InheritAgent(agent); OverrideInstructionByChannel(agent); AddOrUpdateParameters(agent); // Populate state into dictionary - agent.TemplateDict = new Dictionary(); PopulateState(agent.TemplateDict); // After agent is loaded diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs index f862482c..89979663 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs @@ -1,5 +1,6 @@ using BotSharp.Abstraction.Loggers; using BotSharp.Abstraction.Templating; +using Microsoft.EntityFrameworkCore; using Newtonsoft.Json.Linq; namespace BotSharp.Core.Agents.Services; @@ -137,4 +138,20 @@ public partial class AgentService return content; } + + public bool RenderUtility(Agent agent, AgentUtility utility) + { + if (string.IsNullOrWhiteSpace(utility?.VisibilityExpression)) + { + return true; + } + + var render = _services.GetRequiredService(); + var result = render.Render(utility.VisibilityExpression, new Dictionary + { + { "states", agent.TemplateDict } + }); + + return result == "visible"; + } } \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentUtilityMongoElement.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentUtilityMongoElement.cs index 131226b3..518939cc 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentUtilityMongoElement.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentUtilityMongoElement.cs @@ -7,6 +7,7 @@ public class AgentUtilityMongoElement { public string Name { get; set; } = default!; public bool Disabled { get; set; } + public string? VisibilityExpression { get; set; } public List Functions { get; set; } = []; public List Templates { get; set; } = []; @@ -16,6 +17,7 @@ public class AgentUtilityMongoElement { Name = utility.Name, Disabled = utility.Disabled, + VisibilityExpression = utility.VisibilityExpression, Functions = utility.Functions?.Select(x => new UtilityFunctionMongoElement(x.Name))?.ToList() ?? [], Templates = utility.Templates?.Select(x => new UtilityTemplateMongoElement(x.Name))?.ToList() ?? [] }; @@ -27,6 +29,7 @@ public class AgentUtilityMongoElement { Name = utility.Name, Disabled = utility.Disabled, + VisibilityExpression = utility.VisibilityExpression, Functions = utility.Functions?.Select(x => new UtilityFunction(x.Name))?.ToList() ?? [], Templates = utility.Templates?.Select(x => new UtilityTemplate(x.Name))?.ToList() ?? [] }; diff --git a/tests/BotSharp.LLM.Tests/Core/TestAgentService.cs b/tests/BotSharp.LLM.Tests/Core/TestAgentService.cs index 6716519a..7d58637d 100644 --- a/tests/BotSharp.LLM.Tests/Core/TestAgentService.cs +++ b/tests/BotSharp.LLM.Tests/Core/TestAgentService.cs @@ -6,6 +6,7 @@ using BotSharp.Abstraction.Models; using BotSharp.Abstraction.Plugins.Models; using BotSharp.Abstraction.Repositories.Filters; using BotSharp.Abstraction.Utilities; +using NetTopologySuite.Algorithm; namespace BotSharp.Plugin.Google.Core { @@ -61,6 +62,11 @@ namespace BotSharp.Plugin.Google.Core return def.Parameters; } + public bool RenderUtility(Agent agent, AgentUtility utility) + { + return true; + } + public Task GetAgent(string id) { return Task.FromResult(new Agent()); From 59eb471deefc0c8ec8916cb19708a3ed731cbb3f Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Tue, 27 May 2025 15:26:11 -0500 Subject: [PATCH 02/10] minor change --- .../BotSharp.Core/Agents/Hooks/BasicAgentHook.cs | 8 +------- .../Agents/Services/AgentService.Rendering.cs | 1 - 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs b/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs index 03e7bb68..64113c10 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs @@ -66,13 +66,7 @@ public class BasicAgentHook : AgentHookBase var innerUtilities = utilities!.Where(x => { var isVisible = !string.IsNullOrEmpty(x.Name) && !x.Disabled; - if (!isVisible) - { - return isVisible; - } - - isVisible = agentService.RenderUtility(agent, x); - return isVisible; + return isVisible && agentService.RenderUtility(agent, x); }).ToList(); var functionNames = innerUtilities.SelectMany(x => x.Functions) diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs index 89979663..f160a211 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs @@ -1,6 +1,5 @@ using BotSharp.Abstraction.Loggers; using BotSharp.Abstraction.Templating; -using Microsoft.EntityFrameworkCore; using Newtonsoft.Json.Linq; namespace BotSharp.Core.Agents.Services; From 1792da38ef078f5cf92e9a730bdfa55d839fa8d5 Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Wed, 28 May 2025 16:16:48 -0500 Subject: [PATCH 03/10] refine utility structure --- .../Agents/IAgentService.cs | 2 +- .../Agents/Models/AgentUtility.cs | 78 ++++++++++--------- .../BotSharp.Core.Crontab/Enum/UtilityName.cs | 2 +- .../Hooks/CrontabUtilityHook.cs | 14 +++- .../Agents/Hooks/BasicAgentHook.cs | 38 +++++---- .../Agents/Services/AgentService.Rendering.cs | 24 ++---- .../Instructs/Hooks/InstructUtilityHook.cs | 11 ++- .../Routing/Hooks/RoutingUtilityHook.cs | 15 +++- .../Controllers/AgentController.cs | 4 +- .../Enums/UtilityName.cs | 2 +- .../Hooks/AudioHandlerUtilityHook.cs | 10 ++- .../Enums/UtilityName.cs | 2 +- .../Hooks/EmailHandlerUtilityHook.cs | 15 +++- .../Enums/UtilityName.cs | 8 +- .../Hooks/FileHandlerUtilityHook.cs | 39 ++++++++-- .../Enums/UtilityName.cs | 2 +- .../Hooks/HttpHandlerUtilityHook.cs | 10 ++- .../Enum/UtilityName.cs | 2 +- .../Hooks/KnowledgeBaseUtilityHook.cs | 10 ++- .../Models/AgentUtilityMongoElement.cs | 33 ++++---- .../Enums/UtilityName.cs | 2 +- .../Hooks/TwoStagingPlannerUtilityHook.cs | 26 ++++--- .../Hooks/InterpreterUtilityHook.cs | 10 ++- .../Hooks/SqlUtilityHook.cs | 30 ++++--- .../Enums/UtilityName.cs | 2 +- .../OutboundPhoneCallHandlerUtilityHook.cs | 32 +++++--- .../Hooks/WebUtilityHook.cs | 33 +++++--- .../Core/TestAgentService.cs | 2 +- 28 files changed, 296 insertions(+), 162 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs index b50be071..73352892 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs @@ -36,7 +36,7 @@ public interface IAgentService FunctionParametersDef? RenderFunctionProperty(Agent agent, FunctionDef def); - bool RenderUtility(Agent agent, AgentUtility utility); + bool RenderVisibility(string? visibilityExpression, Dictionary dict); /// /// Get agent detail without trigger any hook. diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentUtility.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentUtility.cs index 1d426600..8fc44d7c 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentUtility.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentUtility.cs @@ -2,64 +2,68 @@ namespace BotSharp.Abstraction.Agents.Models; public class AgentUtility { + public string Category { get; set; } public string Name { get; set; } public bool Disabled { get; set; } [JsonPropertyName("visibility_expression")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? VisibilityExpression { get; set; } - public IEnumerable Functions { get; set; } = []; - public IEnumerable Templates { get; set; } = []; + + public IEnumerable Items { get; set; } = []; public AgentUtility() { } - public AgentUtility( - string name, - IEnumerable? functions = null, - IEnumerable? templates = null) - { - Name = name; - Functions = functions ?? []; - Templates = templates ?? []; - } - public override string ToString() { - return Name; + return $"{Category}-{Name}"; } } - -public class UtilityFunction : UtilityBase +public class UtilityItem { - public UtilityFunction() - { + [JsonPropertyName("function_name")] + public string FunctionName { get; set; } = string.Empty; + + [JsonPropertyName("template_name")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? TemplateName { get; set; } + + [JsonPropertyName("visibility_expression")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? VisibilityExpression { get; set; } +} + +//public class UtilityFunction : UtilityBase +//{ +// public UtilityFunction() +// { - } +// } - public UtilityFunction(string name) - { - Name = name; - } -} +// public UtilityFunction(string name) +// { +// Name = name; +// } +//} -public class UtilityTemplate : UtilityBase -{ - public UtilityTemplate() - { +//public class UtilityTemplate : UtilityBase +//{ +// public UtilityTemplate() +// { - } +// } - public UtilityTemplate(string name) - { - Name = name; - } -} +// public UtilityTemplate(string name) +// { +// Name = name; +// } +//} -public class UtilityBase -{ - public string Name { get; set; } -} \ No newline at end of file +//public class UtilityBase +//{ +// public string Name { get; set; } +//} \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.Core.Crontab/Enum/UtilityName.cs b/src/Infrastructure/BotSharp.Core.Crontab/Enum/UtilityName.cs index eba15bd9..5963c8e8 100644 --- a/src/Infrastructure/BotSharp.Core.Crontab/Enum/UtilityName.cs +++ b/src/Infrastructure/BotSharp.Core.Crontab/Enum/UtilityName.cs @@ -2,5 +2,5 @@ namespace BotSharp.Core.Crontab.Enum; public class UtilityName { - public const string ScheduleTask = "crontab.schedule-task"; + public const string ScheduleTask = "schedule-task"; } diff --git a/src/Infrastructure/BotSharp.Core.Crontab/Hooks/CrontabUtilityHook.cs b/src/Infrastructure/BotSharp.Core.Crontab/Hooks/CrontabUtilityHook.cs index 7fed754a..54dd3d06 100644 --- a/src/Infrastructure/BotSharp.Core.Crontab/Hooks/CrontabUtilityHook.cs +++ b/src/Infrastructure/BotSharp.Core.Crontab/Hooks/CrontabUtilityHook.cs @@ -15,9 +15,19 @@ public class CrontabUtilityHook : IAgentUtilityHook { new AgentUtility { + Category = "crontab", Name = UtilityName.ScheduleTask, - Functions = [new(SCHEDULE_TASK_FN), new(TASK_WAIT_FN)], - Templates = [new($"{SCHEDULE_TASK_FN}.fn")] + Items = [ + new UtilityItem + { + FunctionName = SCHEDULE_TASK_FN, + TemplateName = $"{SCHEDULE_TASK_FN}.fn" + }, + new UtilityItem + { + FunctionName = TASK_WAIT_FN + }, + ] } }; diff --git a/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs b/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs index 64113c10..91ded29f 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Hooks/BasicAgentHook.cs @@ -63,21 +63,33 @@ public class BasicAgentHook : AgentHookBase } var agentService = _services.GetRequiredService(); - var innerUtilities = utilities!.Where(x => + var innerUtilities = utilities!.Where(x => !string.IsNullOrEmpty(x.Name) && !x.Disabled).ToList(); + + var functionNames = new List(); + var templateNames = new List(); + + foreach (var utility in innerUtilities) { - var isVisible = !string.IsNullOrEmpty(x.Name) && !x.Disabled; - return isVisible && agentService.RenderUtility(agent, x); - }).ToList(); + var isVisible = agentService.RenderVisibility(utility.VisibilityExpression, agent.TemplateDict); + if (!isVisible || utility.Items.IsNullOrEmpty()) continue; - var functionNames = innerUtilities.SelectMany(x => x.Functions) - .Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX)) - .Select(x => x.Name) - .Distinct().ToList(); - var templateNames = innerUtilities.SelectMany(x => x.Templates) - .Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX)) - .Select(x => x.Name) - .Distinct().ToList(); + foreach (var item in utility.Items) + { + isVisible = agentService.RenderVisibility(item.VisibilityExpression, agent.TemplateDict); + if (!isVisible) continue; - return (functionNames, templateNames); + if (item.FunctionName?.StartsWith(UTIL_PREFIX) == true) + { + functionNames.Add(item.FunctionName); + } + + if (item.TemplateName?.StartsWith(UTIL_PREFIX) == true) + { + templateNames.Add(item.TemplateName); + } + } + } + + return (functionNames.Distinct(), templateNames.Distinct()); } } diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs index f160a211..ffaffb47 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.Rendering.cs @@ -46,12 +46,7 @@ public partial class AgentService if (!string.IsNullOrWhiteSpace(def.VisibilityExpression)) { - var render = _services.GetRequiredService(); - var result = render.Render(def.VisibilityExpression, new Dictionary - { - { "states", agent.TemplateDict } - }); - isRender = isRender && result == "visible"; + isRender = RenderVisibility(def.VisibilityExpression, agent.TemplateDict); } return isRender; @@ -76,12 +71,7 @@ public partial class AgentService if (node.TryGetProperty(visibleExpress, out var element)) { var expression = element.GetString(); - var render = _services.GetRequiredService(); - var result = render.Render(expression, new Dictionary - { - { "states", agent.TemplateDict } - }); - matched = result == "visible"; + matched = RenderVisibility(expression, agent.TemplateDict); } if (matched) @@ -138,19 +128,19 @@ public partial class AgentService return content; } - public bool RenderUtility(Agent agent, AgentUtility utility) + public bool RenderVisibility(string? visibilityExpression, Dictionary dict) { - if (string.IsNullOrWhiteSpace(utility?.VisibilityExpression)) + if (string.IsNullOrWhiteSpace(visibilityExpression)) { return true; } var render = _services.GetRequiredService(); - var result = render.Render(utility.VisibilityExpression, new Dictionary + var result = render.Render(visibilityExpression, new Dictionary { - { "states", agent.TemplateDict } + { "states", dict ?? [] } }); - return result == "visible"; + return result.IsEqualTo("visible"); } } \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.Core/Instructs/Hooks/InstructUtilityHook.cs b/src/Infrastructure/BotSharp.Core/Instructs/Hooks/InstructUtilityHook.cs index e0c6d686..eaee39ca 100644 --- a/src/Infrastructure/BotSharp.Core/Instructs/Hooks/InstructUtilityHook.cs +++ b/src/Infrastructure/BotSharp.Core/Instructs/Hooks/InstructUtilityHook.cs @@ -9,9 +9,14 @@ public class InstructUtilityHook : IAgentUtilityHook { utilities.Add(new AgentUtility { - Name = "instruct.template", - Functions = [new($"{EXECUTE_TEMPLATE}")], - Templates = [new($"{EXECUTE_TEMPLATE}.fn")] + Category = "instruct", + Name = "template", + Items = [ + new UtilityItem { + FunctionName = $"{EXECUTE_TEMPLATE}", + TemplateName = $"{EXECUTE_TEMPLATE}.fn" + } + ] }); } } diff --git a/src/Infrastructure/BotSharp.Core/Routing/Hooks/RoutingUtilityHook.cs b/src/Infrastructure/BotSharp.Core/Routing/Hooks/RoutingUtilityHook.cs index de7a556b..b909bc0f 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Hooks/RoutingUtilityHook.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Hooks/RoutingUtilityHook.cs @@ -10,9 +10,20 @@ public class RoutingUtilityHook : IAgentUtilityHook { utilities.Add(new AgentUtility { + Category = "routing", Name = "routing.tools", - Functions = [new($"{REDIRECT_TO_AGENT}"), new($"{FALLBACK_TO_ROUTER}")], - Templates = [new($"{REDIRECT_TO_AGENT}.fn"), new($"{FALLBACK_TO_ROUTER}.fn")] + Items = [ + new UtilityItem + { + FunctionName = $"{REDIRECT_TO_AGENT}", + TemplateName = $"{REDIRECT_TO_AGENT}.fn" + }, + new UtilityItem + { + FunctionName = $"{FALLBACK_TO_ROUTER}", + TemplateName = $"{FALLBACK_TO_ROUTER}.fn" + } + ] }); } } diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs index 52983506..0e53c746 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs @@ -167,7 +167,9 @@ public class AgentController : ControllerBase { hook.AddUtilities(utilities); } - return utilities.Where(x => !string.IsNullOrWhiteSpace(x.Name)).OrderBy(x => x.Name).ToList(); + return utilities.Where(x => !string.IsNullOrWhiteSpace(x.Category) + && !string.IsNullOrWhiteSpace(x.Name) + && !x.Items.IsNullOrEmpty()).ToList(); } [HttpGet("/agent/labels")] diff --git a/src/Plugins/BotSharp.Plugin.AudioHandler/Enums/UtilityName.cs b/src/Plugins/BotSharp.Plugin.AudioHandler/Enums/UtilityName.cs index 51c86863..d11bd65a 100644 --- a/src/Plugins/BotSharp.Plugin.AudioHandler/Enums/UtilityName.cs +++ b/src/Plugins/BotSharp.Plugin.AudioHandler/Enums/UtilityName.cs @@ -2,5 +2,5 @@ namespace BotSharp.Plugin.AudioHandler.Enums; public class UtilityName { - public const string AudioHandler = "audio.audio-handler"; + public const string AudioHandler = "audio-handler"; } diff --git a/src/Plugins/BotSharp.Plugin.AudioHandler/Hooks/AudioHandlerUtilityHook.cs b/src/Plugins/BotSharp.Plugin.AudioHandler/Hooks/AudioHandlerUtilityHook.cs index 4cb6d61c..9a389d9a 100644 --- a/src/Plugins/BotSharp.Plugin.AudioHandler/Hooks/AudioHandlerUtilityHook.cs +++ b/src/Plugins/BotSharp.Plugin.AudioHandler/Hooks/AudioHandlerUtilityHook.cs @@ -9,9 +9,15 @@ public class AudioHandlerUtilityHook : IAgentUtilityHook { var utility = new AgentUtility { + Category = "audio", Name = UtilityName.AudioHandler, - Functions = [new(HANDLER_AUDIO)], - Templates = [new($"{HANDLER_AUDIO}.fn")] + Items = [ + new UtilityItem + { + FunctionName = HANDLER_AUDIO, + TemplateName = $"{HANDLER_AUDIO}.fn" + } + ] }; utilities.Add(utility); diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/Enums/UtilityName.cs b/src/Plugins/BotSharp.Plugin.EmailHandler/Enums/UtilityName.cs index e9297d8c..d6bc9b01 100644 --- a/src/Plugins/BotSharp.Plugin.EmailHandler/Enums/UtilityName.cs +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/Enums/UtilityName.cs @@ -2,5 +2,5 @@ namespace BotSharp.Plugin.EmailHandler.Enums; public class UtilityName { - public const string EmailHandler = "email.email-handler"; + public const string EmailHandler = "email-handler"; } diff --git a/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerUtilityHook.cs b/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerUtilityHook.cs index a99dfc8c..39c97881 100644 --- a/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerUtilityHook.cs +++ b/src/Plugins/BotSharp.Plugin.EmailHandler/Hooks/EmailHandlerUtilityHook.cs @@ -13,9 +13,20 @@ public class EmailHandlerUtilityHook : IAgentUtilityHook { var utility = new AgentUtility { + Category = "email", Name = UtilityName.EmailHandler, - Functions = [new(EMAIL_READER_FN), new(EMAIL_SENDER_FN)], - Templates = [new($"{EMAIL_READER_FN}.fn"), new($"{EMAIL_SENDER_FN}.fn")] + Items = [ + new UtilityItem + { + FunctionName = EMAIL_READER_FN, + TemplateName = $"{EMAIL_READER_FN}.fn" + }, + new UtilityItem + { + FunctionName = EMAIL_SENDER_FN, + TemplateName = $"{EMAIL_SENDER_FN}.fn" + } + ] }; utilities.Add(utility); diff --git a/src/Plugins/BotSharp.Plugin.FileHandler/Enums/UtilityName.cs b/src/Plugins/BotSharp.Plugin.FileHandler/Enums/UtilityName.cs index 68242202..eb2b4e2b 100644 --- a/src/Plugins/BotSharp.Plugin.FileHandler/Enums/UtilityName.cs +++ b/src/Plugins/BotSharp.Plugin.FileHandler/Enums/UtilityName.cs @@ -2,8 +2,8 @@ namespace BotSharp.Plugin.FileHandler.Enums; public class UtilityName { - public const string ImageGenerator = "file.image-generator"; - public const string ImageReader = "file.image-reader"; - public const string ImageEditor = "file.image-editor"; - public const string PdfReader = "file.pdf-reader"; + public const string ImageGenerator = "image-generator"; + public const string ImageReader = "image-reader"; + public const string ImageEditor = "image-editor"; + public const string PdfReader = "pdf-reader"; } diff --git a/src/Plugins/BotSharp.Plugin.FileHandler/Hooks/FileHandlerUtilityHook.cs b/src/Plugins/BotSharp.Plugin.FileHandler/Hooks/FileHandlerUtilityHook.cs index 3409c448..ab2ee2ab 100644 --- a/src/Plugins/BotSharp.Plugin.FileHandler/Hooks/FileHandlerUtilityHook.cs +++ b/src/Plugins/BotSharp.Plugin.FileHandler/Hooks/FileHandlerUtilityHook.cs @@ -13,27 +13,50 @@ public class FileHandlerUtilityHook : IAgentUtilityHook { new AgentUtility { + Category = "file", Name = UtilityName.ImageGenerator, - Functions = [new(GENERATE_IMAGE_FN)], - Templates = [new($"{GENERATE_IMAGE_FN}.fn")] + Items = [ + new UtilityItem + { + FunctionName = GENERATE_IMAGE_FN, + TemplateName = $"{GENERATE_IMAGE_FN}.fn" + } + ] }, new AgentUtility { + Category = "file", Name = UtilityName.ImageReader, - Functions = [new(READ_IMAGE_FN)], - Templates = [new($"{READ_IMAGE_FN}.fn")] + Items = [ + new UtilityItem + { + FunctionName = READ_IMAGE_FN, + TemplateName = $"{READ_IMAGE_FN}.fn" + } + ] }, new AgentUtility { Name = UtilityName.ImageEditor, - Functions = [new(EDIT_IMAGE_FN)], - Templates = [new($"{EDIT_IMAGE_FN}.fn")] + Items = [ + new UtilityItem + { + FunctionName = EDIT_IMAGE_FN, + TemplateName = $"{EDIT_IMAGE_FN}.fn" + } + ] }, new AgentUtility { + Category = "file", Name = UtilityName.PdfReader, - Functions = [new(READ_PDF_FN)], - Templates = [new($"{READ_PDF_FN}.fn")] + Items = [ + new UtilityItem + { + FunctionName = READ_PDF_FN, + TemplateName = $"{READ_PDF_FN}.fn" + } + ] } }; diff --git a/src/Plugins/BotSharp.Plugin.HttpHandler/Enums/UtilityName.cs b/src/Plugins/BotSharp.Plugin.HttpHandler/Enums/UtilityName.cs index 3a1e7cd5..2e0146bf 100644 --- a/src/Plugins/BotSharp.Plugin.HttpHandler/Enums/UtilityName.cs +++ b/src/Plugins/BotSharp.Plugin.HttpHandler/Enums/UtilityName.cs @@ -2,5 +2,5 @@ namespace BotSharp.Plugin.HttpHandler.Enums; public class UtilityName { - public const string HttpHandler = "http.http-handler"; + public const string HttpHandler = "http-handler"; } diff --git a/src/Plugins/BotSharp.Plugin.HttpHandler/Hooks/HttpHandlerUtilityHook.cs b/src/Plugins/BotSharp.Plugin.HttpHandler/Hooks/HttpHandlerUtilityHook.cs index d99b6084..786380c6 100644 --- a/src/Plugins/BotSharp.Plugin.HttpHandler/Hooks/HttpHandlerUtilityHook.cs +++ b/src/Plugins/BotSharp.Plugin.HttpHandler/Hooks/HttpHandlerUtilityHook.cs @@ -11,9 +11,15 @@ public class HttpHandlerUtilityHook : IAgentUtilityHook { var utility = new AgentUtility { + Category = "http", Name = UtilityName.HttpHandler, - Functions = [new(HTTP_HANDLER_FN)], - Templates = [new($"{HTTP_HANDLER_FN}.fn")] + Items = [ + new UtilityItem + { + FunctionName = HTTP_HANDLER_FN, + TemplateName = $"{HTTP_HANDLER_FN}.fn" + } + ] }; utilities.Add(utility); diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Enum/UtilityName.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Enum/UtilityName.cs index e4518344..0f1e15a5 100644 --- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Enum/UtilityName.cs +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Enum/UtilityName.cs @@ -2,5 +2,5 @@ namespace BotSharp.Plugin.KnowledgeBase.Enum; public class UtilityName { - public const string KnowledgeRetrieval = "kg.knowledge-base"; + public const string KnowledgeRetrieval = "knowledge-base"; } diff --git a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Hooks/KnowledgeBaseUtilityHook.cs b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Hooks/KnowledgeBaseUtilityHook.cs index 84254841..aab73b57 100644 --- a/src/Plugins/BotSharp.Plugin.KnowledgeBase/Hooks/KnowledgeBaseUtilityHook.cs +++ b/src/Plugins/BotSharp.Plugin.KnowledgeBase/Hooks/KnowledgeBaseUtilityHook.cs @@ -9,9 +9,15 @@ public class KnowledgeBaseUtilityHook : IAgentUtilityHook { var utility = new AgentUtility { + Category = "knowledge", Name = UtilityName.KnowledgeRetrieval, - Functions = [new(KNOWLEDGE_RETRIEVAL_FN)], - Templates = [new($"{KNOWLEDGE_RETRIEVAL_FN}.fn")] + Items = [ + new UtilityItem + { + FunctionName = KNOWLEDGE_RETRIEVAL_FN, + TemplateName = $"{KNOWLEDGE_RETRIEVAL_FN}.fn" + } + ] }; utilities.Add(utility); diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentUtilityMongoElement.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentUtilityMongoElement.cs index 518939cc..d7ab6d2a 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentUtilityMongoElement.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentUtilityMongoElement.cs @@ -5,21 +5,26 @@ namespace BotSharp.Plugin.MongoStorage.Models; [BsonIgnoreExtraElements(Inherited = true)] public class AgentUtilityMongoElement { + public string Category { get; set; } = default!; public string Name { get; set; } = default!; public bool Disabled { get; set; } public string? VisibilityExpression { get; set; } - public List Functions { get; set; } = []; - public List Templates { get; set; } = []; + public List Items { get; set; } = []; public static AgentUtilityMongoElement ToMongoElement(AgentUtility utility) { return new AgentUtilityMongoElement { + Category = utility.Category, Name = utility.Name, Disabled = utility.Disabled, VisibilityExpression = utility.VisibilityExpression, - Functions = utility.Functions?.Select(x => new UtilityFunctionMongoElement(x.Name))?.ToList() ?? [], - Templates = utility.Templates?.Select(x => new UtilityTemplateMongoElement(x.Name))?.ToList() ?? [] + Items = utility.Items?.Select(x => new AgentUtilityItemMongoElement + { + FunctionName = x.FunctionName, + TemplateName = x.TemplateName, + VisibilityExpression = x.VisibilityExpression + })?.ToList() ?? [] }; } @@ -27,21 +32,23 @@ public class AgentUtilityMongoElement { return new AgentUtility { + Category = utility.Category, Name = utility.Name, Disabled = utility.Disabled, VisibilityExpression = utility.VisibilityExpression, - Functions = utility.Functions?.Select(x => new UtilityFunction(x.Name))?.ToList() ?? [], - Templates = utility.Templates?.Select(x => new UtilityTemplate(x.Name))?.ToList() ?? [] + Items = utility.Items?.Select(x => new UtilityItem + { + FunctionName = x.FunctionName, + TemplateName = x.TemplateName, + VisibilityExpression = x.VisibilityExpression + })?.ToList() ?? [], }; } } -public class UtilityFunctionMongoElement(string name) +public class AgentUtilityItemMongoElement { - public string Name { get; set; } = name; -} - -public class UtilityTemplateMongoElement(string name) -{ - public string Name { get; set; } = name; + public string FunctionName { get; set; } = string.Empty; + public string? TemplateName { get; set; } + public string? VisibilityExpression { get; set; } } \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.Planner/Enums/UtilityName.cs b/src/Plugins/BotSharp.Plugin.Planner/Enums/UtilityName.cs index 7594fae0..8a3ef6e3 100644 --- a/src/Plugins/BotSharp.Plugin.Planner/Enums/UtilityName.cs +++ b/src/Plugins/BotSharp.Plugin.Planner/Enums/UtilityName.cs @@ -2,5 +2,5 @@ namespace BotSharp.Plugin.Planner.Enums; public class UtilityName { - public const string TwoStagePlanner = "planner.two-stage-planner"; + public const string TwoStagePlanner = "two-stage-planner"; } diff --git a/src/Plugins/BotSharp.Plugin.Planner/TwoStaging/Hooks/TwoStagingPlannerUtilityHook.cs b/src/Plugins/BotSharp.Plugin.Planner/TwoStaging/Hooks/TwoStagingPlannerUtilityHook.cs index 80dfad57..cd41bed4 100644 --- a/src/Plugins/BotSharp.Plugin.Planner/TwoStaging/Hooks/TwoStagingPlannerUtilityHook.cs +++ b/src/Plugins/BotSharp.Plugin.Planner/TwoStaging/Hooks/TwoStagingPlannerUtilityHook.cs @@ -10,16 +10,24 @@ public class TwoStagingPlannerUtilityHook : IAgentUtilityHook { var utility = new AgentUtility { + Category = "planner", Name = UtilityName.TwoStagePlanner, - Functions = [ - new(PRIMARY_STAGE_FN), - new(SECONDARY_STAGE_FN), - new(SUMMARY_FN) - ], - Templates = [ - new($"{PRIMARY_STAGE_FN}.fn"), - new($"{SECONDARY_STAGE_FN}.fn"), - new($"{SUMMARY_FN}.fn") + Items = [ + new UtilityItem + { + FunctionName = PRIMARY_STAGE_FN, + TemplateName = $"{PRIMARY_STAGE_FN}.fn" + }, + new UtilityItem + { + FunctionName = SECONDARY_STAGE_FN, + TemplateName = $"{SECONDARY_STAGE_FN}.fn" + }, + new UtilityItem + { + FunctionName = SUMMARY_FN, + TemplateName = $"{SUMMARY_FN}.fn" + } ] }; diff --git a/src/Plugins/BotSharp.Plugin.PythonInterpreter/Hooks/InterpreterUtilityHook.cs b/src/Plugins/BotSharp.Plugin.PythonInterpreter/Hooks/InterpreterUtilityHook.cs index 540870be..7b644be2 100644 --- a/src/Plugins/BotSharp.Plugin.PythonInterpreter/Hooks/InterpreterUtilityHook.cs +++ b/src/Plugins/BotSharp.Plugin.PythonInterpreter/Hooks/InterpreterUtilityHook.cs @@ -8,9 +8,15 @@ public class InterpreterUtilityHook : IAgentUtilityHook { var utility = new AgentUtility() { + Category = "coding", Name = UtilityName.PythonInterpreter, - Functions = [new(FUNCTION_NAME)], - Templates = [new($"{FUNCTION_NAME}.fn")] + Items = [ + new UtilityItem + { + FunctionName = FUNCTION_NAME, + TemplateName = $"{FUNCTION_NAME}.fn" + } + ] }; utilities.Add(utility); diff --git a/src/Plugins/BotSharp.Plugin.SqlDriver/Hooks/SqlUtilityHook.cs b/src/Plugins/BotSharp.Plugin.SqlDriver/Hooks/SqlUtilityHook.cs index 6756b8c0..760076c6 100644 --- a/src/Plugins/BotSharp.Plugin.SqlDriver/Hooks/SqlUtilityHook.cs +++ b/src/Plugins/BotSharp.Plugin.SqlDriver/Hooks/SqlUtilityHook.cs @@ -14,18 +14,24 @@ public class SqlUtilityHook : IAgentUtilityHook { new AgentUtility { - Name = "db.tools", - Functions = - [ - new(SQL_TABLE_DEFINITION_FN), - new(VERIFY_DICTIONARY_TERM_FN), - new(SQL_SELECT_FN), - ], - Templates = - [ - new($"{VERIFY_DICTIONARY_TERM_FN}.fn"), - new($"{SQL_TABLE_DEFINITION_FN}.fn"), - new($"{SQL_EXECUTOR_FN}.fn") + Category = "database", + Name = "sql.tools", + Items = [ + new UtilityItem + { + FunctionName = SQL_TABLE_DEFINITION_FN, + TemplateName = $"{SQL_TABLE_DEFINITION_FN}.fn" + }, + new UtilityItem + { + FunctionName = VERIFY_DICTIONARY_TERM_FN, + TemplateName = $"{VERIFY_DICTIONARY_TERM_FN}.fn" + }, + new UtilityItem + { + FunctionName = SQL_SELECT_FN, + TemplateName = $"{SQL_EXECUTOR_FN}.fn" + } ] } }; diff --git a/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Enums/UtilityName.cs b/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Enums/UtilityName.cs index b7244e7d..3795f320 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Enums/UtilityName.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Enums/UtilityName.cs @@ -2,6 +2,6 @@ namespace BotSharp.Plugin.Twilio.OutboundPhoneCallHandler.Enums { public class UtilityName { - public const string OutboundPhoneCall = "phone.twilio-phone-call"; + public const string OutboundPhoneCall = "twilio-phone-call"; } } diff --git a/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Hooks/OutboundPhoneCallHandlerUtilityHook.cs b/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Hooks/OutboundPhoneCallHandlerUtilityHook.cs index 58999457..5bd48a3c 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Hooks/OutboundPhoneCallHandlerUtilityHook.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Hooks/OutboundPhoneCallHandlerUtilityHook.cs @@ -16,17 +16,29 @@ public class OutboundPhoneCallHandlerUtilityHook : IAgentUtilityHook { var utility = new AgentUtility { + Category = "phone", Name = UtilityName.OutboundPhoneCall, - Functions = - [ - new($"{OUTBOUND_PHONE_CALL_FN}"), - new($"{TRANSFER_PHONE_CALL_FN}"), - new($"{HANGUP_PHONE_CALL_FN}"), - new($"{TEXT_MESSAGE_FN}"), - new($"{LEAVE_VOICEMAIL_FN}") - ], - Templates = - [ + Items = [ + new UtilityItem + { + FunctionName = OUTBOUND_PHONE_CALL_FN + }, + new UtilityItem + { + FunctionName = TRANSFER_PHONE_CALL_FN + }, + new UtilityItem + { + FunctionName = HANGUP_PHONE_CALL_FN + }, + new UtilityItem + { + FunctionName = TEXT_MESSAGE_FN + }, + new UtilityItem + { + FunctionName = LEAVE_VOICEMAIL_FN + } ] }; diff --git a/src/Plugins/BotSharp.Plugin.WebDriver/Hooks/WebUtilityHook.cs b/src/Plugins/BotSharp.Plugin.WebDriver/Hooks/WebUtilityHook.cs index 63637119..36f69357 100644 --- a/src/Plugins/BotSharp.Plugin.WebDriver/Hooks/WebUtilityHook.cs +++ b/src/Plugins/BotSharp.Plugin.WebDriver/Hooks/WebUtilityHook.cs @@ -14,18 +14,27 @@ public class WebUtilityHook : IAgentUtilityHook { new AgentUtility { - Name = "web.tools", - Functions = - [ - new(CLOSE_BROWSER_FN), - new(GO_TO_PAGE_FN), - new(LOCATE_ELEMENT_FN), - new(ACTION_ON_ELEMENT_FN) - ], - Templates = - [ - new($"{GO_TO_PAGE_FN}.fn"), - new($"{ACTION_ON_ELEMENT_FN}.fn") + Category = "web", + Name = "browser.tools", + Items = [ + new UtilityItem + { + FunctionName = GO_TO_PAGE_FN, + TemplateName = $"{GO_TO_PAGE_FN}.fn" + }, + new UtilityItem + { + FunctionName = ACTION_ON_ELEMENT_FN, + TemplateName = $"{ACTION_ON_ELEMENT_FN}.fn" + }, + new UtilityItem + { + FunctionName = LOCATE_ELEMENT_FN + }, + new UtilityItem + { + FunctionName = CLOSE_BROWSER_FN + } ] } }; diff --git a/tests/BotSharp.LLM.Tests/Core/TestAgentService.cs b/tests/BotSharp.LLM.Tests/Core/TestAgentService.cs index 7d58637d..afaf2899 100644 --- a/tests/BotSharp.LLM.Tests/Core/TestAgentService.cs +++ b/tests/BotSharp.LLM.Tests/Core/TestAgentService.cs @@ -62,7 +62,7 @@ namespace BotSharp.Plugin.Google.Core return def.Parameters; } - public bool RenderUtility(Agent agent, AgentUtility utility) + public bool RenderVisibility(string? visibilityExpression, Dictionary dict) { return true; } From 1d0284eef46da769de3e8fb837e8789435d9f5dd Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Wed, 28 May 2025 16:53:45 -0500 Subject: [PATCH 04/10] minor change --- .../Hooks/ExcelHandlerUtilityHook.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Plugins/BotSharp.Plugin.ExcelHandler/Hooks/ExcelHandlerUtilityHook.cs b/src/Plugins/BotSharp.Plugin.ExcelHandler/Hooks/ExcelHandlerUtilityHook.cs index 6293a832..89d82766 100644 --- a/src/Plugins/BotSharp.Plugin.ExcelHandler/Hooks/ExcelHandlerUtilityHook.cs +++ b/src/Plugins/BotSharp.Plugin.ExcelHandler/Hooks/ExcelHandlerUtilityHook.cs @@ -9,9 +9,15 @@ public class ExcelHandlerUtilityHook : IAgentUtilityHook { var utility = new AgentUtility { + Category = "file", Name = UtilityName.ExcelHandler, - Functions = [new(HANDLER_EXCEL)], - Templates = [new($"{HANDLER_EXCEL}.fn")] + Items = [ + new UtilityItem + { + FunctionName = HANDLER_EXCEL, + TemplateName = $"{HANDLER_EXCEL}.fn" + } + ] }; utilities.Add(utility); From a33d43c9028cdcae19973eb5c466cdfbac53277c Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Wed, 28 May 2025 17:15:37 -0500 Subject: [PATCH 05/10] minor change --- src/Plugins/BotSharp.Plugin.ExcelHandler/Enums/UtilityName.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Plugins/BotSharp.Plugin.ExcelHandler/Enums/UtilityName.cs b/src/Plugins/BotSharp.Plugin.ExcelHandler/Enums/UtilityName.cs index bc689259..66ef3f36 100644 --- a/src/Plugins/BotSharp.Plugin.ExcelHandler/Enums/UtilityName.cs +++ b/src/Plugins/BotSharp.Plugin.ExcelHandler/Enums/UtilityName.cs @@ -2,5 +2,5 @@ namespace BotSharp.Plugin.ExcelHandler.Enums; public class UtilityName { - public const string ExcelHandler = "excel.excel-handler"; + public const string ExcelHandler = "excel-handler"; } From 3bb50a63500799deb8fd762ab65dcc1711efe7af Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Wed, 28 May 2025 18:00:11 -0500 Subject: [PATCH 06/10] nullable --- .../Agents/Models/AgentUtility.cs | 36 ++----------------- .../Models/AgentUtilityMongoElement.cs | 2 +- .../Functions/OutboundPhoneCallFn.cs | 1 - 3 files changed, 4 insertions(+), 35 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentUtility.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentUtility.cs index 8fc44d7c..6233dfa7 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentUtility.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/Models/AgentUtility.cs @@ -26,7 +26,8 @@ public class AgentUtility public class UtilityItem { [JsonPropertyName("function_name")] - public string FunctionName { get; set; } = string.Empty; + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? FunctionName { get; set; } [JsonPropertyName("template_name")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -35,35 +36,4 @@ public class UtilityItem [JsonPropertyName("visibility_expression")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? VisibilityExpression { get; set; } -} - -//public class UtilityFunction : UtilityBase -//{ -// public UtilityFunction() -// { - -// } - -// public UtilityFunction(string name) -// { -// Name = name; -// } -//} - -//public class UtilityTemplate : UtilityBase -//{ -// public UtilityTemplate() -// { - -// } - -// public UtilityTemplate(string name) -// { -// Name = name; -// } -//} - -//public class UtilityBase -//{ -// public string Name { get; set; } -//} \ No newline at end of file +} \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentUtilityMongoElement.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentUtilityMongoElement.cs index d7ab6d2a..be052a1e 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentUtilityMongoElement.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/AgentUtilityMongoElement.cs @@ -48,7 +48,7 @@ public class AgentUtilityMongoElement public class AgentUtilityItemMongoElement { - public string FunctionName { get; set; } = string.Empty; + public string? FunctionName { get; set; } public string? TemplateName { get; set; } public string? VisibilityExpression { get; set; } } \ No newline at end of file diff --git a/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/OutboundPhoneCallFn.cs b/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/OutboundPhoneCallFn.cs index 88586ea8..5ffd692e 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/OutboundPhoneCallFn.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/OutboundPhoneCallFn.cs @@ -1,5 +1,4 @@ using BotSharp.Abstraction.Files; -using BotSharp.Abstraction.Files.Models; using BotSharp.Abstraction.Infrastructures.Enums; using BotSharp.Abstraction.Options; using BotSharp.Abstraction.Routing; From d222a120ac984907bbf4659f680b8f4bb562fb9e Mon Sep 17 00:00:00 2001 From: "nick.yi" Date: Thu, 29 May 2025 10:33:22 +0800 Subject: [PATCH 07/10] hotfix AddDefaultInstruction --- .../Agents/Services/AgentService.GetAgents.cs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs index d9baafb7..576002f2 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs @@ -71,13 +71,25 @@ public partial class AgentService profile.Plugin = GetPlugin(profile.Id); - //add default instruction to ChannelInstructions - var defaultInstruction = new ChannelInstruction() { Channel = string.Empty, Instruction = profile?.Instruction }; - profile.ChannelInstructions.Insert(0, defaultInstruction); + AddDefaultInstruction(profile, profile.Instruction); return profile; } + /// + /// Add default instruction to ChannelInstructions + /// + private void AddDefaultInstruction(Agent agent, string instruction) + { + //check if instruction is empty + if (string.IsNullOrWhiteSpace(instruction)) return; + //check if instruction is already set + if (agent.ChannelInstructions.Exists(p => p.Channel == string.Empty)) return; + //Add default instruction to ChannelInstructions + var defaultInstruction = new ChannelInstruction() { Channel = string.Empty, Instruction = instruction }; + agent.ChannelInstructions.Insert(0, defaultInstruction); + } + public async Task InheritAgent(Agent agent) { if (string.IsNullOrWhiteSpace(agent?.InheritAgentId)) return; @@ -98,6 +110,7 @@ public partial class AgentService if (string.IsNullOrWhiteSpace(agent.Instruction)) { agent.Instruction = inheritedAgent.Instruction; + AddDefaultInstruction(agent, inheritedAgent.Instruction); } } } From 5bfb8f87341627c035d471d770c05aec924bbddc Mon Sep 17 00:00:00 2001 From: "nick.yi" Date: Thu, 29 May 2025 15:14:44 +0800 Subject: [PATCH 08/10] optimize summary --- .../Conversations/IConversationService.cs | 3 +-- .../Models/ConversationSummaryModel.cs | 27 +++++++++++++++++++ .../Services/ConversationService.Summary.cs | 17 ++++++------ .../Controllers/ConversationController.cs | 2 +- .../Request/ConversationSummaryModel.cs | 9 ------- 5 files changed, 38 insertions(+), 20 deletions(-) create mode 100644 src/Infrastructure/BotSharp.Abstraction/Models/ConversationSummaryModel.cs delete mode 100644 src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/Request/ConversationSummaryModel.cs diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs index 4eb44ae4..656b397d 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs @@ -1,4 +1,3 @@ -using BotSharp.Abstraction.Loggers.Models; using BotSharp.Abstraction.Repositories.Filters; namespace BotSharp.Abstraction.Conversations; @@ -53,7 +52,7 @@ public interface IConversationService /// Task UpdateBreakpoint(bool resetStates = false, string? reason = null, params string[] excludedStates); - Task GetConversationSummary(IEnumerable conversationId); + Task GetConversationSummary(ConversationSummaryModel model); Task GetConversationRecordOrCreateNew(string agentId); diff --git a/src/Infrastructure/BotSharp.Abstraction/Models/ConversationSummaryModel.cs b/src/Infrastructure/BotSharp.Abstraction/Models/ConversationSummaryModel.cs new file mode 100644 index 00000000..00860e2e --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Models/ConversationSummaryModel.cs @@ -0,0 +1,27 @@ +using System.Text.Json.Serialization; + +namespace BotSharp.Abstraction.Models; + +public class ConversationSummaryModel +{ + [JsonPropertyName("conversation_ids")] + public IEnumerable ConversationIds { get; set; } = new List(); + + private string _agentId; + + [JsonPropertyName("agent_id")] + public string AgentId + { + get => _agentId ?? BuiltInAgentId.AIAssistant; + set => _agentId = value; + } + + private string _templateName; + + [JsonPropertyName("template_name")] + public string TemplateName + { + get => _templateName ?? "conversation.summary"; + set => _templateName = value; + } +} diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.Summary.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.Summary.cs index 88d3a52d..ba141e08 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.Summary.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.Summary.cs @@ -1,20 +1,21 @@ using BotSharp.Abstraction.Conversations.Enums; using BotSharp.Abstraction.MLTasks; +using BotSharp.Abstraction.Models; using BotSharp.Abstraction.Templating; namespace BotSharp.Core.Conversations.Services; public partial class ConversationService { - public async Task GetConversationSummary(IEnumerable conversationIds) + public async Task GetConversationSummary(ConversationSummaryModel model) { - if (conversationIds.IsNullOrEmpty()) return string.Empty; + if (model.ConversationIds.IsNullOrEmpty()) return string.Empty; var routing = _services.GetRequiredService(); var agentService = _services.GetRequiredService(); var contents = new List(); - foreach ( var conversationId in conversationIds) + foreach (var conversationId in model.ConversationIds) { if (string.IsNullOrEmpty(conversationId)) continue; @@ -31,16 +32,16 @@ public partial class ConversationService if (contents.IsNullOrEmpty()) return string.Empty; - var router = await agentService.LoadAgent(AIAssistant); - var prompt = GetPrompt(router, contents); - var summary = await Summarize(router, prompt); + var agent = await agentService.LoadAgent(model.AgentId); + var prompt = GetPrompt(agent, model.TemplateName, contents); + var summary = await Summarize(agent, prompt); return summary; } - private string GetPrompt(Agent agent, List contents) + private string GetPrompt(Agent agent, string templateName, List contents) { - var template = agent.Templates.First(x => x.Name == "conversation.summary").Content; + var template = agent.Templates.First(x => x.Name == templateName).Content; var render = _services.GetRequiredService(); var texts = new List(); diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs index bcb92f74..d3da550f 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs @@ -185,7 +185,7 @@ public class ConversationController : ControllerBase public async Task GetConversationSummary([FromBody] ConversationSummaryModel input) { var service = _services.GetRequiredService(); - return await service.GetConversationSummary(input.ConversationIds); + return await service.GetConversationSummary(input); } [HttpPut("/conversation/{conversationId}/update-title")] diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/Request/ConversationSummaryModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/Request/ConversationSummaryModel.cs deleted file mode 100644 index 0854ab2a..00000000 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/Request/ConversationSummaryModel.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Text.Json.Serialization; - -namespace BotSharp.OpenAPI.ViewModels.Conversations; - -public class ConversationSummaryModel -{ - [JsonPropertyName("conversation_ids")] - public List ConversationIds { get; set; } = new List(); -} From 365c1db3836c700203fcb8a7c412398665056e7b Mon Sep 17 00:00:00 2001 From: Haiping Date: Thu, 29 May 2025 05:04:20 -0500 Subject: [PATCH 09/10] Update Directory.Packages.props --- Directory.Packages.props | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index e5f4fcd6..cec2ac88 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -35,7 +35,7 @@ - + @@ -132,12 +132,12 @@ - + - - + + @@ -147,4 +147,4 @@ - \ No newline at end of file + From 854e6bf11dfd49e56584b0dac61f6d3027b1f145 Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Thu, 29 May 2025 05:39:07 -0500 Subject: [PATCH 10/10] OnTicketReceivedContext --- .../Users/IAuthenticationHook.cs | 19 +++++++--- .../Users/Services/UserService.cs | 2 +- .../BotSharpOpenApiExtensions.cs | 36 +++++++++++++++---- 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs b/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs index 21522a57..a8403dfa 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs @@ -1,4 +1,5 @@ using BotSharp.Abstraction.Users.Models; +using Microsoft.AspNetCore.Authentication; using System.Security.Claims; namespace BotSharp.Abstraction.Users; @@ -11,7 +12,8 @@ public interface IAuthenticationHook /// /// /// - Task Authenticate(string id, string password); + Task Authenticate(string id, string password) + => Task.FromResult(new User()); /// /// Add extra claims to user @@ -30,31 +32,38 @@ public interface IAuthenticationHook bool UserAuthenticated(User user, Token token) => true; + Task OAuthCompleted(TicketReceivedContext context) + => Task.CompletedTask; + /// /// Bfore user updating /// /// /// - Task UserUpdating(User user); + Task UserUpdating(User user) + => Task.CompletedTask; /// /// After user created /// /// /// - Task UserCreated(User user); + Task UserCreated(User user) + => Task.CompletedTask; /// /// Reset password /// /// /// - Task SendVerificationCode(User user); + Task SendVerificationCode(User user) + => Task.CompletedTask; /// /// Delete users /// /// /// - Task DelUsers(List userIds); + Task DelUsers(List userIds) + => Task.CompletedTask; } diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs index e4ebe311..e076026b 100644 --- a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs +++ b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs @@ -254,7 +254,7 @@ public class UserService : IUserService foreach (var hook in hooks) { user = await hook.Authenticate(id, password); - if (user == null) + if (user == null || string.IsNullOrEmpty(user.Id)) { continue; } diff --git a/src/Infrastructure/BotSharp.OpenAPI/BotSharpOpenApiExtensions.cs b/src/Infrastructure/BotSharp.OpenAPI/BotSharpOpenApiExtensions.cs index a1a6dad2..6136fc6c 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/BotSharpOpenApiExtensions.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/BotSharpOpenApiExtensions.cs @@ -11,6 +11,8 @@ using Microsoft.Net.Http.Headers; using Microsoft.OpenApi.Models; using Microsoft.IdentityModel.JsonWebTokens; using BotSharp.OpenAPI.BackgroundServices; +using System.Text.Json.Serialization; +using Microsoft.AspNetCore.Authentication; namespace BotSharp.OpenAPI; @@ -61,6 +63,9 @@ public static class BotSharpOpenApiExtensions } }).AddCookie(options => { + // Add these lines for cross-origin cookie support + options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None; + options.Cookie.SecurePolicy = CookieSecurePolicy.Always; }).AddPolicyScheme(schema, "Mixed authentication", options => { // runs on each request @@ -82,15 +87,16 @@ public static class BotSharpOpenApiExtensions }; }); + #region OpenId // GitHub OAuth if (!string.IsNullOrWhiteSpace(config["OAuth:GitHub:ClientId"]) && !string.IsNullOrWhiteSpace(config["OAuth:GitHub:ClientSecret"])) { builder = builder.AddGitHub(options => - { - options.ClientId = config["OAuth:GitHub:ClientId"]; - options.ClientSecret = config["OAuth:GitHub:ClientSecret"]; - options.Scope.Add("user:email"); - }); + { + options.ClientId = config["OAuth:GitHub:ClientId"]; + options.ClientSecret = config["OAuth:GitHub:ClientSecret"]; + options.Events.OnTicketReceived = OnTicketReceivedContext; + }); } // Google Identiy OAuth @@ -100,6 +106,7 @@ public static class BotSharpOpenApiExtensions { options.ClientId = config["OAuth:Google:ClientId"]; options.ClientSecret = config["OAuth:Google:ClientSecret"]; + options.Events.OnTicketReceived = OnTicketReceivedContext; }); } @@ -113,8 +120,9 @@ public static class BotSharpOpenApiExtensions options.ClientId = config["OAuth:Keycloak:ClientId"]; options.ClientSecret = config["OAuth:Keycloak:ClientSecret"]; options.AccessType = AspNet.Security.OAuth.Keycloak.KeycloakAuthenticationAccessType.Confidential; - int version = Convert.ToInt32(config["OAuth:Keycloak:Version"]??"22") ; - options.Version = new Version(version,0); + int version = Convert.ToInt32(config["OAuth:Keycloak:Version"] ?? "22"); + options.Version = new Version(version, 0); + options.Events.OnTicketReceived = OnTicketReceivedContext; }); } @@ -129,13 +137,17 @@ public static class BotSharpOpenApiExtensions options.Backchannel = builder.Services.BuildServiceProvider() .GetRequiredService() .CreateClient(); + options.Events.OnTicketReceived = OnTicketReceivedContext; }); } + #endregion // Add services to the container. services.AddControllers() .AddJsonOptions(options => { + options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; + options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); options.JsonSerializerOptions.Converters.Add(new RichContentJsonConverter()); options.JsonSerializerOptions.Converters.Add(new TemplateMessageJsonConverter()); }); @@ -182,6 +194,16 @@ public static class BotSharpOpenApiExtensions return services; } + private static async Task OnTicketReceivedContext(TicketReceivedContext context) + { + var services = context.HttpContext.RequestServices; + var hooks = services.GetServices(); + foreach (var hook in hooks) + { + await hook.OAuthCompleted(context); + } + } + /// /// Use Swagger/OpenAPI ///