diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs index afae2e00..804e21ef 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs @@ -1,4 +1,6 @@ using BotSharp.Abstraction.Functions.Models; +using BotSharp.Abstraction.Messaging.Models; +using BotSharp.Abstraction.Messaging.Models.RichContent; namespace BotSharp.Abstraction.Conversations.Models; @@ -35,7 +37,7 @@ public class RoleDialogModel : ITrackableMessage [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public object Data { get; set; } [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public object? RichContent { get; set; } + public RichContent? RichContent { get; set; } /// /// Stop conversation completion diff --git a/src/Infrastructure/BotSharp.Abstraction/Functions/Models/FunctionCallFromLlm.cs b/src/Infrastructure/BotSharp.Abstraction/Functions/Models/FunctionCallFromLlm.cs index 7ea31a47..92b37efa 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Functions/Models/FunctionCallFromLlm.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Functions/Models/FunctionCallFromLlm.cs @@ -12,6 +12,8 @@ public class FunctionCallFromLlm : RoutingArgs [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public JsonDocument? Arguments { get; set; } + public bool IsExecutionOnce { get; set; } + public override string ToString() { var route = string.IsNullOrEmpty(AgentName) ? "" : $""; diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/IMessageTemplate.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/IMessageTemplate.cs new file mode 100644 index 00000000..357dc937 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/IMessageTemplate.cs @@ -0,0 +1,6 @@ +namespace BotSharp.Abstraction.Messaging.Models; + +public interface IMessageTemplate +{ + string Text { get; set; } +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/QuickReplyElement.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/QuickReplyElement.cs index 1be8f208..cea110f1 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/QuickReplyElement.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/QuickReplyElement.cs @@ -9,7 +9,6 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent public string? Payload { get; set; } [JsonPropertyName("image_url")] public string? ImageUrl { get; set; } - [JsonPropertyName("postback_url")] public string? PostBackUrl { get; set; } } } diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/QuickReplyMessage.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/QuickReplyMessage.cs index b14b27e1..b7c273e8 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/QuickReplyMessage.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/QuickReplyMessage.cs @@ -1,8 +1,10 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent { - public class QuickReplyMessage : TextMessage + public class QuickReplyMessage : IMessageTemplate { + public string Text { get; set; } = string.Empty; + [JsonPropertyName("quick_replies")] public List QuickReplies { get; set; } = new List(); } diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/RichContent.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/RichContent.cs index 221dc96d..18afce0e 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/RichContent.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/RichContent.cs @@ -1,6 +1,6 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent { - public class RichContent + public class RichContent where T : IMessageTemplate { public Recipient Recipient { get; set; } = new Recipient(); /// diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/AttachmentTemplate.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/AttachmentTemplate.cs deleted file mode 100644 index 89f2137e..00000000 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/AttachmentTemplate.cs +++ /dev/null @@ -1,9 +0,0 @@ - -namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template -{ - public class AttachmentTemplate - { - public string Type => "template"; - public T Payload { get; set; } - } -} diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ButtonTemplate.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ButtonTemplate.cs index f610a682..9119901a 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ButtonTemplate.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ButtonTemplate.cs @@ -1,8 +1,10 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template { - public class ButtonTemplate : TextMessage + public class ButtonTemplate : IMessageTemplate { + public string Text { get; set; } = string.Empty; + [JsonPropertyName("template_type")] public string TemplateType => "button"; public List Buttons { get; set; } = new List(); diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/MultiSelectTemplate.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/MultiSelectTemplate.cs index d0ec8ffb..caab4ca3 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/MultiSelectTemplate.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/MultiSelectTemplate.cs @@ -1,8 +1,10 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template { - public class MultiSelectTemplate : TextMessage + public class MultiSelectTemplate : IMessageTemplate { + public string Text { get; set; } = string.Empty; + [JsonPropertyName("template_type")] public string TemplateType => "multi-select"; public List Options { get; set; } = new List(); diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/TemplateMessage.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/TemplateMessage.cs deleted file mode 100644 index 77b4a55f..00000000 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/TemplateMessage.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template -{ - public class TemplateMessage - { - public T Attachment { get; set; } - } -} diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/TextMessage.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/TextMessage.cs index 94d85894..1cc8918a 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/TextMessage.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/TextMessage.cs @@ -1,8 +1,7 @@ -namespace BotSharp.Abstraction.Messaging.Models.RichContent +namespace BotSharp.Abstraction.Messaging.Models.RichContent; + +public class TextMessage : IMessageTemplate { - public class TextMessage - { - public string Text { get; set; } = string.Empty; - } + public string Text { get; set; } = string.Empty; } \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContentJsonConverter .cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContentJsonConverter .cs new file mode 100644 index 00000000..d194d687 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContentJsonConverter .cs @@ -0,0 +1,16 @@ +using System.Text.Json; + +namespace BotSharp.Abstraction.Messaging.Models; + +public class RichContentJsonConverter : JsonConverter +{ + public override IMessageTemplate? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + + public override void Write(Utf8JsonWriter writer, IMessageTemplate value, JsonSerializerOptions options) + { + JsonSerializer.Serialize(writer, value, value.GetType(), options); + } +} diff --git a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj index 1b789f1f..8099a315 100644 --- a/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj +++ b/src/Infrastructure/BotSharp.Core/BotSharp.Core.csproj @@ -56,7 +56,6 @@ - diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs index 19ddfee9..2e087cf2 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.SendMessage.cs @@ -1,4 +1,5 @@ using BotSharp.Abstraction.Agents.Models; +using BotSharp.Abstraction.Messaging.Models; using BotSharp.Abstraction.Messaging.Models.RichContent; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Settings; @@ -102,7 +103,7 @@ public partial class ConversationService // Only read content from RichContent for UI rendering. When richContent is null, create a basic text message for richContent. var state = _services.GetRequiredService(); - response.RichContent = response.RichContent ?? new RichContent + response.RichContent = response.RichContent ?? new RichContent { Recipient = new Recipient { Id = state.GetConversationId() }, Message = new TextMessage { Text = response.Content } diff --git a/src/Infrastructure/BotSharp.Core/Planning/InstructExecutor.cs b/src/Infrastructure/BotSharp.Core/Planning/InstructExecutor.cs index 0d02cd95..47d6ccce 100644 --- a/src/Infrastructure/BotSharp.Core/Planning/InstructExecutor.cs +++ b/src/Infrastructure/BotSharp.Core/Planning/InstructExecutor.cs @@ -1,4 +1,6 @@ using BotSharp.Abstraction.Functions.Models; +using BotSharp.Abstraction.Messaging.Models; +using BotSharp.Abstraction.Messaging.Models.RichContent; using BotSharp.Abstraction.Planning; using BotSharp.Abstraction.Routing; @@ -33,6 +35,14 @@ public class InstructExecutor : IExecutor response.MessageId = message.MessageId; response.Instruction = inst; + // Process rich content + if (response.RichContent != null && + response.RichContent is RichContent template && + string.IsNullOrEmpty(template.Message.Text)) + { + template.Message.Text = response.Content; + } + return response; } } diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs index 0f03955a..39b53285 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs @@ -36,6 +36,10 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler var ret = await function.Execute(message); var agentId = context.GetCurrentAgentId(); + if (inst.IsExecutionOnce) + { + message.Content = inst.Question; + } ret = await routing.InvokeAgent(agentId, _dialogs); var response = _dialogs.Last(); diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs index bba2c30c..1ce7cfb7 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs @@ -44,7 +44,9 @@ public partial class RoutingService : IRoutingService Function = "route_to_agent", Question = message.Content, Reason = message.Content, - AgentName = agent.Name + AgentName = agent.Name, + OriginalAgent = agent.Name, + IsExecutionOnce = true }; var result = await handler.Handle(this, inst, message);