From 18cb89219fcfd4990e47cce14c40aee27b0e5346 Mon Sep 17 00:00:00 2001 From: "nick.yi" Date: Wed, 22 Apr 2026 14:20:33 +0800 Subject: [PATCH 1/2] feat(conversation): add ExcludeFromContext flag, drop record_only message type --- .../Conversations/Enums/MessageTypeName.cs | 4 ---- .../Conversations/Models/Conversation.cs | 6 ++++++ .../Conversations/Models/RoleDialogModel.cs | 6 ++++++ .../Conversations/Services/ConversationService.cs | 3 +-- .../Conversations/Services/ConversationStorage.cs | 3 +++ .../Routing/RoutingService.GetConversationContent.cs | 4 +--- .../BotSharp.Core/Routing/RoutingService.InvokeAgent.cs | 2 +- .../Models/DialogMongoElement.cs | 3 +++ 8 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/MessageTypeName.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/MessageTypeName.cs index e87fa669b..e59622bb6 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/MessageTypeName.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/MessageTypeName.cs @@ -3,10 +3,6 @@ namespace BotSharp.Abstraction.Conversations.Enums; public static class MessageTypeName { public const string Plain = "plain"; - /// - /// Persisted for record/audit but excluded from default LLM dialog history. - /// - public const string RecordOnly = "record_only"; public const string Notification = "notification"; public const string FunctionCall = "function"; public const string Audio = "audio"; diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/Conversation.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/Conversation.cs index 411ca0842..1aea4ef8a 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/Conversation.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/Conversation.cs @@ -121,6 +121,12 @@ public class DialogMetaData [JsonPropertyName("sender_id")] public string? SenderId { get; set; } + /// + /// When true, message is persisted but omitted from default LLM dialog history and routing conversation text. + /// + [JsonPropertyName("exclude_from_context")] + public bool ExcludeFromContext { get; set; } + [JsonPropertyName("create_at")] public DateTime CreatedTime { get; set; } } \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs index 796ee93d7..7c1f757eb 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs @@ -19,6 +19,11 @@ public class RoleDialogModel : ITrackableMessage /// public string MessageType { get; set; } = MessageTypeName.Plain; + /// + /// When true, message is stored but omitted from default LLM history and routing [CONVERSATION] (orthogonal to ). + /// + public bool ExcludeFromContext { get; set; } + /// /// The message label /// @@ -191,6 +196,7 @@ public static RoleDialogModel From(RoleDialogModel source, CurrentAgentId = source.CurrentAgentId, MessageId = source.MessageId, MessageType = source.MessageType, + ExcludeFromContext = source.ExcludeFromContext, MessageLabel = source.MessageLabel, ToolCallId = source.ToolCallId, FunctionName = source.FunctionName, diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs index 1b71f5efa..9cffd3d9d 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs @@ -169,8 +169,7 @@ public async Task> GetDialogHistory(int lastCount = 100, b } else { - var defaultMessageTypes = new List { MessageTypeName.Plain, MessageTypeName.RecordOnly }; - dialogs = dialogs.Where(x => string.IsNullOrEmpty(x.MessageType) || defaultMessageTypes.Contains(x.MessageType)).ToList(); + dialogs = dialogs.Where(x => string.IsNullOrEmpty(x.MessageType) || x.MessageType.IsEqualTo(MessageTypeName.Plain)).ToList(); } if (fromBreakpoint) diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStorage.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStorage.cs index d2dc3a99d..d735a832c 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStorage.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStorage.cs @@ -75,6 +75,7 @@ public async Task> GetDialogs(string conversationId, Conve CurrentAgentId = meta?.AgentId ?? string.Empty, MessageId = meta?.MessageId ?? string.Empty, MessageType = meta?.MessageType ?? string.Empty, + ExcludeFromContext = meta?.ExcludeFromContext ?? false, MessageLabel = meta?.MessageLabel, CreatedAt = meta?.CreatedTime ?? default, SenderId = senderId, @@ -115,6 +116,7 @@ public async Task> GetDialogs(string conversationId, Conve AgentId = dialog.CurrentAgentId, MessageId = dialog.MessageId, MessageType = dialog.MessageType, + ExcludeFromContext = dialog.ExcludeFromContext, MessageLabel = dialog.MessageLabel, ToolCallId = dialog.ToolCallId, FunctionName = dialog.FunctionName, @@ -143,6 +145,7 @@ public async Task> GetDialogs(string conversationId, Conve AgentId = dialog.CurrentAgentId, MessageId = dialog.MessageId, MessageType = dialog.MessageType, + ExcludeFromContext = dialog.ExcludeFromContext, MessageLabel = dialog.MessageLabel, SenderId = dialog.SenderId, FunctionName = dialog.FunctionName, diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetConversationContent.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetConversationContent.cs index b468d3afa..256f5d065 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetConversationContent.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetConversationContent.cs @@ -1,5 +1,3 @@ -using BotSharp.Abstraction.Conversations.Enums; - namespace BotSharp.Core.Routing; public partial class RoutingService @@ -8,7 +6,7 @@ public async Task GetConversationContent(List dialogs, { var agentService = _services.GetRequiredService(); var conversation = ""; - var conversationDialogs = dialogs.Where(x => x.MessageType != MessageTypeName.RecordOnly).TakeLast(maxDialogCount).ToList(); + var conversationDialogs = dialogs.Where(x => !x.ExcludeFromContext).TakeLast(maxDialogCount).ToList(); foreach (var dialog in conversationDialogs) { var role = dialog.Role; diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs index c00332c6a..c773ef714 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeAgent.cs @@ -38,7 +38,7 @@ public async Task InvokeAgent( RoleDialogModel response; var message = dialogs.Last(); - var conversationDialogs = dialogs.Where(x => x.MessageType != MessageTypeName.RecordOnly).ToList(); + var conversationDialogs = dialogs.Where(x => !x.ExcludeFromContext).ToList(); if (options?.UseStream == true) { response = await chatCompletion.GetChatCompletionsStreamingAsync(agent, conversationDialogs); diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/DialogMongoElement.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/DialogMongoElement.cs index ff70bdab8..19611baa9 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/DialogMongoElement.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/DialogMongoElement.cs @@ -52,6 +52,7 @@ public class DialogMetaDataMongoElement public string? FunctionArgs { get; set; } public Dictionary? MetaData { get; set; } public string? SenderId { get; set; } + public bool ExcludeFromContext { get; set; } public DateTime CreateTime { get; set; } public static DialogMetaData ToDomainElement(DialogMetaDataMongoElement meta) @@ -68,6 +69,7 @@ public static DialogMetaData ToDomainElement(DialogMetaDataMongoElement meta) FunctionArgs = meta.FunctionArgs, MetaData = meta.MetaData, SenderId = meta.SenderId, + ExcludeFromContext = meta.ExcludeFromContext, CreatedTime = meta.CreateTime }; } @@ -86,6 +88,7 @@ public static DialogMetaDataMongoElement ToMongoElement(DialogMetaData meta) FunctionArgs = meta.FunctionArgs, MetaData = meta.MetaData, SenderId = meta.SenderId, + ExcludeFromContext = meta.ExcludeFromContext, CreateTime = meta.CreatedTime }; } From 1bba400e4a49604089cd548070a9acf2142e75bb Mon Sep 17 00:00:00 2001 From: "nick.yi" Date: Wed, 22 Apr 2026 14:25:10 +0800 Subject: [PATCH 2/2] chore: remove unused MessageTypeName.Notification --- .../BotSharp.Abstraction/Conversations/Enums/MessageTypeName.cs | 1 - .../Conversations/Services/ConversationService.Summary.cs | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/MessageTypeName.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/MessageTypeName.cs index e59622bb6..c1ab00028 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/MessageTypeName.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Enums/MessageTypeName.cs @@ -3,7 +3,6 @@ namespace BotSharp.Abstraction.Conversations.Enums; public static class MessageTypeName { public const string Plain = "plain"; - public const string Notification = "notification"; public const string FunctionCall = "function"; public const string Audio = "audio"; public const string Error = "error"; diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.Summary.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.Summary.cs index e2c06c609..aa90d1014 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.Summary.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.Summary.cs @@ -1,4 +1,3 @@ -using BotSharp.Abstraction.Conversations.Enums; using BotSharp.Abstraction.MLTasks; using BotSharp.Abstraction.Models; using BotSharp.Abstraction.Settings; @@ -24,7 +23,6 @@ public async Task GetConversationSummary(ConversationSummaryModel model) if (dialogs.IsNullOrEmpty()) continue; - dialogs = dialogs.Where(x => x.MessageType != MessageTypeName.Notification).ToList(); var content = GetConversationContent(dialogs); if (string.IsNullOrWhiteSpace(content)) continue;