From a6d57e417c77affdb276c8485b3ee745d3d5c7b6 Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Tue, 2 Apr 2024 09:44:40 -0500 Subject: [PATCH 1/5] minor change --- .../Messaging/JsonConverters/RichContentJsonConverter .cs | 1 - .../Messaging/JsonConverters/TemplateMessageJsonConverter.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/RichContentJsonConverter .cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/RichContentJsonConverter .cs index 502b0785..98230871 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/RichContentJsonConverter .cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/RichContentJsonConverter .cs @@ -9,7 +9,6 @@ public class RichContentJsonConverter : JsonConverter { using var jsonDoc = JsonDocument.ParseValue(ref reader); var root = jsonDoc.RootElement; - var jsonText = root.GetRawText(); var res = MessageParser.ParseRichMessage(root, options); return res; } diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/TemplateMessageJsonConverter.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/TemplateMessageJsonConverter.cs index f0f14730..da5fcfd1 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/TemplateMessageJsonConverter.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/TemplateMessageJsonConverter.cs @@ -9,7 +9,6 @@ public class TemplateMessageJsonConverter : JsonConverter { using var jsonDoc = JsonDocument.ParseValue(ref reader); var root = jsonDoc.RootElement; - var jsonText = root.GetRawText(); var res = MessageParser.ParseTemplateMessage(root, options); return res; } From 7ae9e3ef60f2c62d89c6ad95069861fc600f1183 Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Tue, 2 Apr 2024 11:38:18 -0500 Subject: [PATCH 2/5] refine states --- .../BotSharp.Abstraction.csproj | 1 + .../Conversations/Enums/StateDataType.cs | 10 ++++++ .../Conversations/Enums/StateSource.cs | 8 +++++ .../IConversationStateService.cs | 4 ++- .../Conversations/Models/StateKeyValue.cs | 21 +++++++++++ ...sageParser.cs => BotSharpMessageParser.cs} | 29 ++++++++------- .../RichContentJsonConverter .cs | 2 +- .../TemplateMessageJsonConverter.cs | 2 +- .../Services/ConversationStateService.cs | 35 ++++++++++++------- 9 files changed, 84 insertions(+), 28 deletions(-) create mode 100644 src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/StateDataType.cs create mode 100644 src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/StateSource.cs rename src/Infrastructure/BotSharp.Abstraction/Messaging/{MessageParser.cs => BotSharpMessageParser.cs} (75%) diff --git a/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj b/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj index bbade11e..65424adb 100644 --- a/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj +++ b/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj @@ -22,6 +22,7 @@ + diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/StateDataType.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/StateDataType.cs new file mode 100644 index 00000000..20d635f4 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/StateDataType.cs @@ -0,0 +1,10 @@ +namespace BotSharp.Abstraction.Conversations.Enums; + +public class StateDataType +{ + public const string String = "string"; + public const string Boolean = "boolean"; + public const string Number = "number"; + public const string Currency = "currency"; + public const string Date = "date"; +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/StateSource.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/StateSource.cs new file mode 100644 index 00000000..31f32e16 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/StateSource.cs @@ -0,0 +1,8 @@ +namespace BotSharp.Abstraction.Conversations.Enums; + +public class StateSource +{ + public const string External = "external"; + public const string Application = "application"; + public const string User = "user"; +} diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs index 07eab6c1..d71111fd 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs @@ -1,3 +1,4 @@ +using BotSharp.Abstraction.Conversations.Enums; using System.Text.Json; namespace BotSharp.Abstraction.Conversations; @@ -12,7 +13,8 @@ public interface IConversationStateService string GetState(string name, string defaultValue = ""); bool ContainsState(string name); Dictionary GetStates(); - IConversationStateService SetState(string name, T value, bool isNeedVersion = true, int activeRounds = -1); + IConversationStateService SetState(string name, T value, bool isNeedVersion = true, + int activeRounds = -1, string valueType = StateDataType.String, string source = StateSource.User); void SaveStateByArgs(JsonDocument args); void CleanStates(); void Save(); diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateKeyValue.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateKeyValue.cs index 53618242..c70dbf03 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateKeyValue.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateKeyValue.cs @@ -1,3 +1,5 @@ +using BotSharp.Abstraction.Conversations.Enums; + namespace BotSharp.Abstraction.Conversations.Models; public class StateKeyValue @@ -16,6 +18,12 @@ public class StateKeyValue Key = key; Values = values; } + + public override string ToString() + { + var lastValue = Values.LastOrDefault(); + return $"{Key} => ({lastValue?.ToString()})"; + } } public class StateValue @@ -30,6 +38,12 @@ public class StateValue [JsonPropertyName("active_rounds")] public int ActiveRounds { get; set; } + [JsonPropertyName("data_type")] + public string DataType { get; set; } = StateDataType.String; + + [JsonPropertyName("source")] + public string Source { get; set; } + [JsonPropertyName("update_time")] public DateTime UpdateTime { get; set; } @@ -37,4 +51,11 @@ public class StateValue { } + + public override string ToString() + { + var isActive = Active ? "Yes" : "No"; + var activeRounds = ActiveRounds <= 0 ? "infinity" : ActiveRounds.ToString(); + return $"Data: {Data}, Active: {isActive}, Active rounds: {activeRounds}, Source: {Source}"; + } } \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/MessageParser.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/BotSharpMessageParser.cs similarity index 75% rename from src/Infrastructure/BotSharp.Abstraction/Messaging/MessageParser.cs rename to src/Infrastructure/BotSharp.Abstraction/Messaging/BotSharpMessageParser.cs index b739709c..6697ef34 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/MessageParser.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/BotSharpMessageParser.cs @@ -3,10 +3,13 @@ using BotSharp.Abstraction.Messaging.Enums; using BotSharp.Abstraction.Messaging.Models.RichContent.Template; using BotSharp.Abstraction.Messaging.Models.RichContent; using System.Text.Json; +using System.Reflection; +using Newtonsoft.Json; +using JsonSerializer = System.Text.Json.JsonSerializer; namespace BotSharp.Core.Messaging; -public static class MessageParser +public static class BotSharpMessageParser { public static IRichMessage? ParseRichMessage(JsonElement root, JsonSerializerOptions options) @@ -43,13 +46,13 @@ public static class MessageParser if (root.TryGetProperty("element_type", out element)) { var elementType = element.GetString(); - if (elementType == typeof(GenericElement).Name) + var wrapperType = typeof(GenericTemplateMessage<>); + var genericType = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(x => x.Name == elementType); + + if (wrapperType != null && genericType != null) { - res = JsonSerializer.Deserialize>(jsonText, options); - } - else if (elementType == typeof(ButtonElement).Name) - { - res = JsonSerializer.Deserialize>(jsonText, options); + var targetType = wrapperType.MakeGenericType(genericType); + res = JsonConvert.DeserializeObject(jsonText, targetType) as IRichMessage; } } } @@ -88,13 +91,13 @@ public static class MessageParser if (root.TryGetProperty("element_type", out element)) { var elementType = element.GetString(); - if (elementType == typeof(GenericElement).Name) + var wrapperType = typeof(GenericTemplateMessage<>); + var genericType = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(x => x.Name == elementType); + + if (wrapperType != null && genericType != null) { - res = JsonSerializer.Deserialize>(jsonText, options); - } - else if (elementType == typeof(ButtonElement).Name) - { - res = JsonSerializer.Deserialize>(jsonText, options); + var targetType = wrapperType.MakeGenericType(genericType); + res = JsonConvert.DeserializeObject(jsonText, targetType) as ITemplateMessage; } } } diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/RichContentJsonConverter .cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/RichContentJsonConverter .cs index 98230871..94d12796 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/RichContentJsonConverter .cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/RichContentJsonConverter .cs @@ -9,7 +9,7 @@ public class RichContentJsonConverter : JsonConverter { using var jsonDoc = JsonDocument.ParseValue(ref reader); var root = jsonDoc.RootElement; - var res = MessageParser.ParseRichMessage(root, options); + var res = BotSharpMessageParser.ParseRichMessage(root, options); return res; } diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/TemplateMessageJsonConverter.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/TemplateMessageJsonConverter.cs index da5fcfd1..84963d39 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/TemplateMessageJsonConverter.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/TemplateMessageJsonConverter.cs @@ -9,7 +9,7 @@ public class TemplateMessageJsonConverter : JsonConverter { using var jsonDoc = JsonDocument.ParseValue(ref reader); var root = jsonDoc.RootElement; - var res = MessageParser.ParseTemplateMessage(root, options); + var res = BotSharpMessageParser.ParseTemplateMessage(root, options); return res; } diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs index 9356e2f5..32fbb30a 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs @@ -1,3 +1,4 @@ +using BotSharp.Abstraction.Conversations.Enums; using BotSharp.Abstraction.Users.Enums; namespace BotSharp.Core.Conversations.Services; @@ -33,7 +34,8 @@ public class ConversationStateService : IConversationStateService, IDisposable /// /// whether the state is related to message or not /// - public IConversationStateService SetState(string name, T value, bool isNeedVersion = true, int activeRounds = -1) + public IConversationStateService SetState(string name, T value, bool isNeedVersion = true, + int activeRounds = -1, string valueType = StateDataType.String, string source = StateSource.User) { if (value == null) { @@ -56,18 +58,21 @@ public class ConversationStateService : IConversationStateService, IDisposable _logger.LogInformation($"[STATE] {name} = {value}"); var routingCtx = _services.GetRequiredService(); - foreach (var hook in hooks) + if (!ContainsState(name) || preValue != currentValue || preActiveRounds != curActiveRounds) { - hook.OnStateChanged(new StateChangeModel + foreach (var hook in hooks) { - ConversationId = _conversationId, - MessageId = routingCtx.MessageId, - Name = name, - BeforeValue = preValue, - BeforeActiveRounds = preActiveRounds, - AfterValue = currentValue, - AfterActiveRounds = curActiveRounds - }).Wait(); + hook.OnStateChanged(new StateChangeModel + { + ConversationId = _conversationId, + MessageId = routingCtx.MessageId, + Name = name, + BeforeValue = preValue, + BeforeActiveRounds = preActiveRounds, + AfterValue = currentValue, + AfterActiveRounds = curActiveRounds + }).Wait(); + } } var newPair = new StateKeyValue @@ -82,6 +87,8 @@ public class ConversationStateService : IConversationStateService, IDisposable MessageId = routingCtx.MessageId, Active = true, ActiveRounds = curActiveRounds, + DataType = valueType, + Source = source, UpdateTime = DateTime.UtcNow, }; @@ -132,6 +139,8 @@ public class ConversationStateService : IConversationStateService, IDisposable MessageId = curMsgId, Active = false, ActiveRounds = value.ActiveRounds, + DataType = value.DataType, + Source = value.Source, UpdateTime = DateTime.UtcNow }); continue; @@ -192,6 +201,8 @@ public class ConversationStateService : IConversationStateService, IDisposable MessageId = curMsgId, Active = false, ActiveRounds = lastValue.ActiveRounds, + DataType = lastValue.DataType, + Source = lastValue.Source, UpdateTime = utcNow }); } @@ -246,7 +257,7 @@ public class ConversationStateService : IConversationStateService, IDisposable { if (!string.IsNullOrEmpty(property.Value.ToString())) { - SetState(property.Name, property.Value); + SetState(property.Name, property.Value, source: StateSource.Application); } } } From 8168b22707ff2e09ca9c435c3b099ab94165f170 Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Tue, 2 Apr 2024 14:09:42 -0500 Subject: [PATCH 3/5] refine element button --- .../Conversations/Models/StateChangeModel.cs | 6 +++ .../Messaging/BotSharpMessageParser.cs | 43 +++++++++++-------- .../RichContentJsonConverter .cs | 3 +- .../TemplateMessageJsonConverter.cs | 3 +- .../Models/RichContent/ElementButton.cs | 10 ++++- .../Template/ButtonTemplateMessage.cs | 21 +-------- .../Services/ConversationService.cs | 3 +- .../Services/ConversationStateService.cs | 4 +- .../Controllers/ConversationController.cs | 11 +++-- .../Hooks/StreamingLogHook.cs | 2 + .../Models/StateMongoElement.cs | 7 +++ 11 files changed, 62 insertions(+), 51 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateChangeModel.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateChangeModel.cs index f98a896d..ea602ad3 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateChangeModel.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateChangeModel.cs @@ -22,4 +22,10 @@ public class StateChangeModel [JsonPropertyName("after_active_rounds")] public int? AfterActiveRounds { get; set; } + + [JsonPropertyName("data_type")] + public string DataType { get; set; } + + [JsonPropertyName("source")] + public string Source { get; set; } } diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/BotSharpMessageParser.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/BotSharpMessageParser.cs index 6697ef34..e22150e9 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/BotSharpMessageParser.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/BotSharpMessageParser.cs @@ -1,20 +1,19 @@ -using BotSharp.Abstraction.Messaging; using BotSharp.Abstraction.Messaging.Enums; using BotSharp.Abstraction.Messaging.Models.RichContent.Template; using BotSharp.Abstraction.Messaging.Models.RichContent; using System.Text.Json; using System.Reflection; using Newtonsoft.Json; -using JsonSerializer = System.Text.Json.JsonSerializer; -namespace BotSharp.Core.Messaging; +namespace BotSharp.Abstraction.Messaging; public static class BotSharpMessageParser { - public static IRichMessage? ParseRichMessage(JsonElement root, JsonSerializerOptions options) + public static IRichMessage? ParseRichMessage(JsonElement root) { IRichMessage? res = null; + Type? targetType = null; JsonElement element; var jsonText = root.GetRawText(); @@ -23,23 +22,23 @@ public static class BotSharpMessageParser var richType = element.GetString(); if (richType == RichTypeEnum.ButtonTemplate) { - res = JsonSerializer.Deserialize(jsonText, options); + targetType = typeof(ButtonTemplateMessage); } else if (richType == RichTypeEnum.MultiSelectTemplate) { - res = JsonSerializer.Deserialize(jsonText, options); + targetType = typeof(MultiSelectTemplateMessage); } else if (richType == RichTypeEnum.QuickReply) { - res = JsonSerializer.Deserialize(jsonText, options); + targetType = typeof(QuickReplyMessage); } else if (richType == RichTypeEnum.CouponTemplate) { - res = JsonSerializer.Deserialize(jsonText, options); + targetType = typeof(CouponTemplateMessage); } else if (richType == RichTypeEnum.Text) { - res = JsonSerializer.Deserialize(jsonText, options); + targetType = typeof(TextMessage); } else if (richType == RichTypeEnum.GenericTemplate) { @@ -51,19 +50,24 @@ public static class BotSharpMessageParser if (wrapperType != null && genericType != null) { - var targetType = wrapperType.MakeGenericType(genericType); - res = JsonConvert.DeserializeObject(jsonText, targetType) as IRichMessage; + targetType = wrapperType.MakeGenericType(genericType); } } } } + if (targetType != null) + { + res = JsonConvert.DeserializeObject(jsonText, targetType) as IRichMessage; + } + return res; } - public static ITemplateMessage? ParseTemplateMessage(JsonElement root, JsonSerializerOptions options) + public static ITemplateMessage? ParseTemplateMessage(JsonElement root) { ITemplateMessage? res = null; + Type? targetType = null; JsonElement element; var jsonText = root.GetRawText(); @@ -72,19 +76,19 @@ public static class BotSharpMessageParser var templateType = element.GetString(); if (templateType == TemplateTypeEnum.Button) { - res = JsonSerializer.Deserialize(jsonText, options); + targetType = typeof(ButtonTemplateMessage); } else if (templateType == TemplateTypeEnum.MultiSelect) { - res = JsonSerializer.Deserialize(jsonText, options); + targetType = typeof(MultiSelectTemplateMessage); } else if (templateType == TemplateTypeEnum.Coupon) { - res = JsonSerializer.Deserialize(jsonText, options); + targetType = typeof(CouponTemplateMessage); } else if (templateType == TemplateTypeEnum.Product) { - res = JsonSerializer.Deserialize(jsonText, options); + targetType = typeof(ProductTemplateMessage); } else if (templateType == TemplateTypeEnum.Generic) { @@ -96,13 +100,18 @@ public static class BotSharpMessageParser if (wrapperType != null && genericType != null) { - var targetType = wrapperType.MakeGenericType(genericType); + targetType = wrapperType.MakeGenericType(genericType); res = JsonConvert.DeserializeObject(jsonText, targetType) as ITemplateMessage; } } } } + if (targetType != null) + { + res = JsonConvert.DeserializeObject(jsonText, targetType) as ITemplateMessage; + } + return res; } } diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/RichContentJsonConverter .cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/RichContentJsonConverter .cs index 94d12796..1748eb5a 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/RichContentJsonConverter .cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/RichContentJsonConverter .cs @@ -1,4 +1,3 @@ -using BotSharp.Core.Messaging; using System.Text.Json; namespace BotSharp.Abstraction.Messaging.JsonConverters; @@ -9,7 +8,7 @@ public class RichContentJsonConverter : JsonConverter { using var jsonDoc = JsonDocument.ParseValue(ref reader); var root = jsonDoc.RootElement; - var res = BotSharpMessageParser.ParseRichMessage(root, options); + var res = BotSharpMessageParser.ParseRichMessage(root); return res; } diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/TemplateMessageJsonConverter.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/TemplateMessageJsonConverter.cs index 84963d39..ce42c489 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/TemplateMessageJsonConverter.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/JsonConverters/TemplateMessageJsonConverter.cs @@ -1,4 +1,3 @@ -using BotSharp.Core.Messaging; using System.Text.Json; namespace BotSharp.Abstraction.Messaging.JsonConverters; @@ -9,7 +8,7 @@ public class TemplateMessageJsonConverter : JsonConverter { using var jsonDoc = JsonDocument.ParseValue(ref reader); var root = jsonDoc.RootElement; - var res = BotSharpMessageParser.ParseTemplateMessage(root, options); + var res = BotSharpMessageParser.ParseTemplateMessage(root); return res; } diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/ElementButton.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/ElementButton.cs index b3642194..bc13660a 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/ElementButton.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/ElementButton.cs @@ -5,13 +5,19 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent; /// public class ElementButton { - public string Type { get; set; } + public string Type { get; set; } = "web_url"; [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string Url { get; set; } - public string Title { get; set; } + public string Title { get; set; } = string.Empty; [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string Payload { get; set; } + + [JsonPropertyName("is_primary")] + public bool IsPrimary { get; set; } + + [JsonPropertyName("is_secondary")] + public bool IsSecondary { get; set; } } diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ButtonTemplateMessage.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ButtonTemplateMessage.cs index 4c92a3fb..32ad73e2 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ButtonTemplateMessage.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ButtonTemplateMessage.cs @@ -17,27 +17,8 @@ public class ButtonTemplateMessage : IRichMessage, ITemplateMessage public string TemplateType => TemplateTypeEnum.Button; [JsonPropertyName("buttons")] - public ButtonElement[] Buttons { get; set; } = new ButtonElement[0]; + public ElementButton[] Buttons { get; set; } = new ElementButton[0]; [JsonPropertyName("is_horizontal")] public bool IsHorizontal { get; set; } } - -public class ButtonElement -{ - /// - /// web_url, postback, phone_number - /// - public string Type { get; set; } = "web_url"; - - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public string? Url { get; set; } - - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public string? Payload { get; set; } - - public string Title { get; set; } = string.Empty; - - [JsonPropertyName("is_primary")] - public bool IsPrimary { get; set; } -} diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs index 8b3bb0fc..188715d4 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs @@ -1,3 +1,4 @@ +using BotSharp.Abstraction.Conversations.Enums; using BotSharp.Abstraction.Models; namespace BotSharp.Core.Conversations.Services; @@ -126,6 +127,6 @@ public partial class ConversationService : IConversationService { _conversationId = conversationId; _state.Load(_conversationId); - states.ForEach(x => _state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds)); + states.ForEach(x => _state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); } } diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs index 32fbb30a..c413d501 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs @@ -70,7 +70,9 @@ public class ConversationStateService : IConversationStateService, IDisposable BeforeValue = preValue, BeforeActiveRounds = preActiveRounds, AfterValue = currentValue, - AfterActiveRounds = curActiveRounds + AfterActiveRounds = curActiveRounds, + DataType = valueType, + Source = source }).Wait(); } } diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs index daf2b116..e01a0f46 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs @@ -1,5 +1,4 @@ using BotSharp.Abstraction.Routing; -using BotSharp.Abstraction.Users.Models; namespace BotSharp.OpenAPI.Controllers; @@ -166,11 +165,11 @@ public class ConversationController : ControllerBase routing.Context.SetMessageId(conversationId, inputMsg.MessageId); conv.SetConversationId(conversationId, input.States); - conv.States.SetState("channel", input.Channel) - .SetState("provider", input.Provider) - .SetState("model", input.Model) - .SetState("temperature", input.Temperature) - .SetState("sampling_factor", input.SamplingFactor); + conv.States.SetState("channel", input.Channel, source: StateSource.External) + .SetState("provider", input.Provider, source: StateSource.External) + .SetState("model", input.Model, source: StateSource.External) + .SetState("temperature", input.Temperature, source: StateSource.External) + .SetState("sampling_factor", input.SamplingFactor, source: StateSource.External); var response = new ChatResponseModel(); diff --git a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs index 2162bcb9..20f7a0a2 100644 --- a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs +++ b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs @@ -436,6 +436,8 @@ public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook, IR BeforeActiveRounds = stateChange.BeforeActiveRounds, AfterValue = stateChange.AfterValue, AfterActiveRounds = stateChange.AfterActiveRounds, + DataType = stateChange.DataType, + Source = stateChange.Source, CreateTime = DateTime.UtcNow }; diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/StateMongoElement.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/StateMongoElement.cs index b56483e1..54f67350 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/StateMongoElement.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/StateMongoElement.cs @@ -35,6 +35,9 @@ public class StateValueMongoElement public string? MessageId { get; set; } public bool Active { get; set; } public int ActiveRounds { get; set; } + public string DataType { get; set; } + public string Source { get; set; } + public DateTime UpdateTime { get; set; } public static StateValueMongoElement ToMongoElement(StateValue element) @@ -45,6 +48,8 @@ public class StateValueMongoElement MessageId = element.MessageId, Active = element.Active, ActiveRounds = element.ActiveRounds, + DataType = element.DataType, + Source = element.Source, UpdateTime = element.UpdateTime }; } @@ -57,6 +62,8 @@ public class StateValueMongoElement MessageId = element.MessageId, Active = element.Active, ActiveRounds = element.ActiveRounds, + DataType= element.DataType, + Source = element.Source, UpdateTime = element.UpdateTime }; } From da42be0477de0dfe3a941a3a479b7243970b9958 Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Tue, 2 Apr 2024 14:24:04 -0500 Subject: [PATCH 4/5] minor change --- .../Conversations/Services/TokenStatistics.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/TokenStatistics.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/TokenStatistics.cs index 1ee38e2e..ca230ff3 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/TokenStatistics.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/TokenStatistics.cs @@ -1,3 +1,4 @@ +using BotSharp.Abstraction.Conversations.Enums; using BotSharp.Abstraction.MLTasks; using System.Diagnostics; using System.Drawing; @@ -47,14 +48,14 @@ public class TokenStatistics : ITokenStatistics // Accumulated Token var stat = _services.GetRequiredService(); var inputCount = int.Parse(stat.GetState("prompt_total", "0")); - stat.SetState("prompt_total", stats.PromptCount + inputCount, false); + stat.SetState("prompt_total", stats.PromptCount + inputCount, isNeedVersion: false, source: StateSource.Application); var outputCount = int.Parse(stat.GetState("completion_total", "0")); - stat.SetState("completion_total", stats.CompletionCount + outputCount, false); + stat.SetState("completion_total", stats.CompletionCount + outputCount, isNeedVersion: false, source: StateSource.Application); // Total cost var total_cost = float.Parse(stat.GetState("llm_total_cost", "0")); total_cost += Cost; - stat.SetState("llm_total_cost", total_cost, false); + stat.SetState("llm_total_cost", total_cost, isNeedVersion: false, source: StateSource.Application); } public void PrintStatistics() From 40bafdc327bff9e0b1ffcd648a2df3520ebd03fe Mon Sep 17 00:00:00 2001 From: Jicheng Lu <103353@smsassist.com> Date: Tue, 2 Apr 2024 15:39:14 -0500 Subject: [PATCH 5/5] add readonly --- .../Conversations/IConversationStateService.cs | 2 +- .../Conversations/Models/StateChangeModel.cs | 3 +++ .../Conversations/Models/StateKeyValue.cs | 1 + .../Conversations/Services/ConversationStateService.cs | 8 +++++--- .../BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs | 1 + .../Models/StateMongoElement.cs | 3 +++ 6 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs index d71111fd..4b28c1d3 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationStateService.cs @@ -14,7 +14,7 @@ public interface IConversationStateService bool ContainsState(string name); Dictionary GetStates(); IConversationStateService SetState(string name, T value, bool isNeedVersion = true, - int activeRounds = -1, string valueType = StateDataType.String, string source = StateSource.User); + int activeRounds = -1, string valueType = StateDataType.String, string source = StateSource.User, bool readOnly = false); void SaveStateByArgs(JsonDocument args); void CleanStates(); void Save(); diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateChangeModel.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateChangeModel.cs index ea602ad3..26c10a71 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateChangeModel.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateChangeModel.cs @@ -28,4 +28,7 @@ public class StateChangeModel [JsonPropertyName("source")] public string Source { get; set; } + + [JsonPropertyName("readonly")] + public bool Readonly { get; set; } } diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateKeyValue.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateKeyValue.cs index c70dbf03..4afea9da 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateKeyValue.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/StateKeyValue.cs @@ -6,6 +6,7 @@ public class StateKeyValue { public string Key { get; set; } public bool Versioning { get; set; } + public bool Readonly { get; set; } public List Values { get; set; } = new List(); public StateKeyValue() diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs index c413d501..b87a8fd7 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStateService.cs @@ -35,7 +35,7 @@ public class ConversationStateService : IConversationStateService, IDisposable /// whether the state is related to message or not /// public IConversationStateService SetState(string name, T value, bool isNeedVersion = true, - int activeRounds = -1, string valueType = StateDataType.String, string source = StateSource.User) + int activeRounds = -1, string valueType = StateDataType.String, string source = StateSource.User, bool readOnly = false) { if (value == null) { @@ -72,7 +72,8 @@ public class ConversationStateService : IConversationStateService, IDisposable AfterValue = currentValue, AfterActiveRounds = curActiveRounds, DataType = valueType, - Source = source + Source = source, + Readonly = readOnly }).Wait(); } } @@ -80,7 +81,8 @@ public class ConversationStateService : IConversationStateService, IDisposable var newPair = new StateKeyValue { Key = name, - Versioning = isNeedVersion + Versioning = isNeedVersion, + Readonly = readOnly }; var newValue = new StateValue diff --git a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs index 20f7a0a2..2e2ed3d6 100644 --- a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs +++ b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs @@ -438,6 +438,7 @@ public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook, IR AfterActiveRounds = stateChange.AfterActiveRounds, DataType = stateChange.DataType, Source = stateChange.Source, + Readonly = stateChange.Readonly, CreateTime = DateTime.UtcNow }; diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/StateMongoElement.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/StateMongoElement.cs index 54f67350..a939f59c 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/StateMongoElement.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/StateMongoElement.cs @@ -6,6 +6,7 @@ public class StateMongoElement { public string Key { get; set; } public bool Versioning { get; set; } + public bool Readonly { get; set; } public List Values { get; set; } public static StateMongoElement ToMongoElement(StateKeyValue state) @@ -14,6 +15,7 @@ public class StateMongoElement { Key = state.Key, Versioning = state.Versioning, + Readonly = state.Readonly, Values = state.Values?.Select(x => StateValueMongoElement.ToMongoElement(x))?.ToList() ?? new List() }; } @@ -24,6 +26,7 @@ public class StateMongoElement { Key = state.Key, Versioning = state.Versioning, + Readonly = state.Readonly, Values = state.Values?.Select(x => StateValueMongoElement.ToDomainElement(x))?.ToList() ?? new List() }; }