diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs index 2ec4ff921..cf49da421 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs @@ -12,6 +12,7 @@ public interface IAgentService Task CreateAgent(Agent agent); Task RefreshAgents(); Task> GetAgents(AgentFilter filter); + Task> GetAgentOptions(); /// /// Load agent configurations and trigger hooks diff --git a/src/Infrastructure/BotSharp.Abstraction/Files/IFileInstructService.cs b/src/Infrastructure/BotSharp.Abstraction/Files/IFileInstructService.cs index f8f4c605a..9ec3c8ed2 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Files/IFileInstructService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Files/IFileInstructService.cs @@ -3,11 +3,11 @@ namespace BotSharp.Abstraction.Files; public interface IFileInstructService { #region Image - Task ReadImages(string? provider, string? model, string text, IEnumerable images); - Task GenerateImage(string? provider, string? model, string text); - Task VaryImage(string? provider, string? model, InstructFileModel image); - Task EditImage(string? provider, string? model, string text, InstructFileModel image); - Task EditImage(string? provider, string? model, string text, InstructFileModel image, InstructFileModel mask); + Task ReadImages(string? provider, string? model, string text, IEnumerable images, string? agentId = null); + Task GenerateImage(string? provider, string? model, string text, string? agentId = null); + Task VaryImage(string? provider, string? model, InstructFileModel image, string? agentId = null); + Task EditImage(string? provider, string? model, string text, InstructFileModel image, string? agentId = null); + Task EditImage(string? provider, string? model, string text, InstructFileModel image, InstructFileModel mask, string? agentId = null); #endregion #region Pdf @@ -17,7 +17,7 @@ public interface IFileInstructService /// /// Pdf files /// - Task ReadPdf(string? provider, string? model, string? modelId, string prompt, List files); + Task ReadPdf(string? provider, string? model, string? modelId, string prompt, List files, string? agentId = null); #endregion #region Audio diff --git a/src/Infrastructure/BotSharp.Abstraction/Models/IdName.cs b/src/Infrastructure/BotSharp.Abstraction/Models/IdName.cs new file mode 100644 index 000000000..e5f7d8b5b --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Models/IdName.cs @@ -0,0 +1,21 @@ +namespace BotSharp.Abstraction.Models; + +public class IdName +{ + [JsonPropertyName("id")] + public string Id { get; set; } = default!; + + [JsonPropertyName("name")] + public string Name { get; set; } = default!; + + public IdName(string id, string name) + { + Id = id; + Name = name; + } + + public override string ToString() + { + return $"{Id}: {Name}"; + } +} diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs index 95018a2d1..ec95a51ec 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs @@ -1,3 +1,4 @@ +using BotSharp.Abstraction.Models; using BotSharp.Abstraction.Routing.Settings; namespace BotSharp.Core.Agents.Services; @@ -26,6 +27,15 @@ public async Task> GetAgents(AgentFilter filter) }; } +#if !DEBUG + [SharpCache(10, perInstanceCache: true)] +#endif + public async Task> GetAgentOptions() + { + var agents = _db.GetAgents(AgentFilter.Empty()); + return agents?.Select(x => new IdName(x.Id, x.Name))?.OrderBy(x => x.Name)?.ToList() ?? []; + } + #if !DEBUG [SharpCache(10, perInstanceCache: true)] #endif diff --git a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Image.cs b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Image.cs index cd65c16a9..4de657c38 100644 --- a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Image.cs +++ b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Image.cs @@ -4,12 +4,12 @@ namespace BotSharp.Core.Files.Services; public partial class FileInstructService { - public async Task ReadImages(string? provider, string? model, string text, IEnumerable images) + public async Task ReadImages(string? provider, string? model, string text, IEnumerable images, string? agentId = null) { var completion = CompletionProvider.GetChatCompletion(_services, provider: provider ?? "openai", model: model ?? "gpt-4o", multiModal: true); var message = await completion.GetChatCompletions(new Agent() { - Id = Guid.Empty.ToString(), + Id = agentId ?? Guid.Empty.ToString(), }, new List { new RoleDialogModel(AgentRole.User, text) @@ -20,17 +20,17 @@ public async Task ReadImages(string? provider, string? model, string tex return message.Content; } - public async Task GenerateImage(string? provider, string? model, string text) + public async Task GenerateImage(string? provider, string? model, string text, string? agentId = null) { var completion = CompletionProvider.GetImageCompletion(_services, provider: provider ?? "openai", model: model ?? "dall-e-3"); var message = await completion.GetImageGeneration(new Agent() { - Id = Guid.Empty.ToString(), + Id = agentId ?? Guid.Empty.ToString(), }, new RoleDialogModel(AgentRole.User, text)); return message; } - public async Task VaryImage(string? provider, string? model, InstructFileModel image) + public async Task VaryImage(string? provider, string? model, InstructFileModel image, string? agentId = null) { if (string.IsNullOrWhiteSpace(image?.FileUrl) && string.IsNullOrWhiteSpace(image?.FileData)) { @@ -46,14 +46,14 @@ public async Task VaryImage(string? provider, string? model, In var fileName = $"{image.FileName ?? "image"}.{image.FileExtension ?? "png"}"; var message = await completion.GetImageVariation(new Agent() { - Id = Guid.Empty.ToString() + Id = agentId ?? Guid.Empty.ToString() }, new RoleDialogModel(AgentRole.User, string.Empty), stream, fileName); stream.Close(); return message; } - public async Task EditImage(string? provider, string? model, string text, InstructFileModel image) + public async Task EditImage(string? provider, string? model, string text, InstructFileModel image, string? agentId = null) { if (string.IsNullOrWhiteSpace(image?.FileUrl) && string.IsNullOrWhiteSpace(image?.FileData)) { @@ -69,14 +69,14 @@ public async Task EditImage(string? provider, string? model, st var fileName = $"{image.FileName ?? "image"}.{image.FileExtension ?? "png"}"; var message = await completion.GetImageEdits(new Agent() { - Id = Guid.Empty.ToString() + Id = agentId ?? Guid.Empty.ToString() }, new RoleDialogModel(AgentRole.User, text), stream, fileName); stream.Close(); return message; } - public async Task EditImage(string? provider, string? model, string text, InstructFileModel image, InstructFileModel mask) + public async Task EditImage(string? provider, string? model, string text, InstructFileModel image, InstructFileModel mask, string? agentId = null) { if ((string.IsNullOrWhiteSpace(image?.FileUrl) && string.IsNullOrWhiteSpace(image?.FileData)) || (string.IsNullOrWhiteSpace(mask?.FileUrl) && string.IsNullOrWhiteSpace(mask?.FileData))) @@ -100,7 +100,7 @@ public async Task EditImage(string? provider, string? model, st var maskName = $"{mask.FileName ?? "mask"}.{mask.FileExtension ?? "png"}"; var message = await completion.GetImageEdits(new Agent() { - Id = Guid.Empty.ToString() + Id = agentId ?? Guid.Empty.ToString() }, new RoleDialogModel(AgentRole.User, text), imageStream, imageName, maskStream, maskName); imageStream.Close(); diff --git a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Pdf.cs b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Pdf.cs index 29dfdaf9a..e1362455a 100644 --- a/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Pdf.cs +++ b/src/Infrastructure/BotSharp.Core/Files/Services/Instruct/FileInstructService.Pdf.cs @@ -4,7 +4,7 @@ namespace BotSharp.Core.Files.Services; public partial class FileInstructService { - public async Task ReadPdf(string? provider, string? model, string? modelId, string prompt, List files) + public async Task ReadPdf(string? provider, string? model, string? modelId, string prompt, List files, string? agentId = null) { var content = string.Empty; @@ -14,7 +14,6 @@ public async Task ReadPdf(string? provider, string? model, string? model } var guid = Guid.NewGuid().ToString(); - var sessionDir = _fileStorage.BuildDirectory(SESSION_FOLDER, guid); DeleteIfExistDirectory(sessionDir, true); @@ -28,7 +27,7 @@ public async Task ReadPdf(string? provider, string? model, string? model model: model, modelId: modelId ?? "gpt-4", multiModal: true); var message = await completion.GetChatCompletions(new Agent() { - Id = Guid.Empty.ToString(), + Id = agentId ?? Guid.Empty.ToString(), }, new List { new RoleDialogModel(AgentRole.User, prompt) diff --git a/src/Infrastructure/BotSharp.Logger/BotSharpLoggerExtensions.cs b/src/Infrastructure/BotSharp.Logger/BotSharpLoggerExtensions.cs index 3ea2cd825..6ccd70acd 100644 --- a/src/Infrastructure/BotSharp.Logger/BotSharpLoggerExtensions.cs +++ b/src/Infrastructure/BotSharp.Logger/BotSharpLoggerExtensions.cs @@ -13,8 +13,8 @@ public static IServiceCollection AddBotSharpLogger(this IServiceCollection servi services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.AddScoped(); - services.AddScoped(); return services; } } diff --git a/src/Infrastructure/BotSharp.Logger/Hooks/GlobalStatsConversationHook.cs b/src/Infrastructure/BotSharp.Logger/Hooks/GlobalStatsConversationHook.cs index 32c4b7d70..2cc2c9fbd 100644 --- a/src/Infrastructure/BotSharp.Logger/Hooks/GlobalStatsConversationHook.cs +++ b/src/Infrastructure/BotSharp.Logger/Hooks/GlobalStatsConversationHook.cs @@ -4,7 +4,7 @@ namespace BotSharp.Logger.Hooks; -public class GlobalStatsConversationHook : ConversationHookBase +public class GlobalStatsConversationHook : IContentGeneratingHook { private readonly IServiceProvider _services; @@ -14,14 +14,10 @@ public GlobalStatsConversationHook( _services = services; } - public override async Task OnMessageReceived(RoleDialogModel message) - { - UpdateAgentCall(message); - } - - public override async Task OnPostbackMessageReceived(RoleDialogModel message, PostbackMessageModel replyMsg) + public async Task AfterGenerated(RoleDialogModel message, TokenStatsModel tokenStats) { UpdateAgentCall(message); + await Task.CompletedTask; } private void UpdateAgentCall(RoleDialogModel message) @@ -33,7 +29,7 @@ private void UpdateAgentCall(RoleDialogModel message) { Metric = StatsMetric.AgentCall, Dimension = "agent", - DimRefVal = message.CurrentAgentId, + DimRefVal = message.CurrentAgentId ?? string.Empty, RecordTime = DateTime.UtcNow, IntervalType = StatsInterval.Day, Data = [ diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs index 4a05b121f..00c82ebe7 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/AgentController.cs @@ -149,6 +149,12 @@ public async Task DeleteAgent([FromRoute] string agentId) return await _agentService.DeleteAgent(agentId); } + [HttpGet("/agent/options")] + public async Task> GetAgentOptions() + { + return await _agentService.GetAgentOptions(); + } + [HttpGet("/agent/utility/options")] public IEnumerable GetAgentUtilityOptions() { diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs index 618627816..433d691af 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/InstructModeController.cs @@ -88,7 +88,7 @@ public async Task MultiModalCompletion([FromBody] MultiModalRequest inpu try { var fileInstruct = _services.GetRequiredService(); - var content = await fileInstruct.ReadImages(input.Provider, input.Model, input.Text, input.Files); + var content = await fileInstruct.ReadImages(input.Provider, input.Model, input.Text, input.Files, input.AgentId); return content; } catch (Exception ex) @@ -101,7 +101,7 @@ public async Task MultiModalCompletion([FromBody] MultiModalRequest inpu [HttpPost("/instruct/multi-modal/upload")] public async Task MultiModalCompletion(IFormFile file, [FromForm] string text, [FromForm] string? provider = null, - [FromForm] string? model = null, [FromForm] List? states = null) + [FromForm] string? model = null, [FromForm] List? states = null, [FromForm] string? agentId = null) { var state = _services.GetRequiredService(); states?.ForEach(x => state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); @@ -115,7 +115,7 @@ public async Task MultiModalCompletion(IFormFile file, [Fro new InstructFileModel { FileData = data } }; var fileInstruct = _services.GetRequiredService(); - var content = await fileInstruct.ReadImages(provider, model, text, files); + var content = await fileInstruct.ReadImages(provider, model, text, files, agentId); viewModel.Content = content; return viewModel; } @@ -140,7 +140,7 @@ public async Task ImageGeneration([FromBody] ImageGene try { var fileInstruct = _services.GetRequiredService(); - var message = await fileInstruct.GenerateImage(input.Provider, input.Model, input.Text); + var message = await fileInstruct.GenerateImage(input.Provider, input.Model, input.Text, input.AgentId); imageViewModel.Content = message.Content; imageViewModel.Images = message.GeneratedImages.Select(x => ImageViewModel.ToViewModel(x)).ToList(); return imageViewModel; @@ -171,7 +171,7 @@ public async Task ImageVariation([FromBody] ImageVaria } var fileInstruct = _services.GetRequiredService(); - var message = await fileInstruct.VaryImage(input.Provider, input.Model, input.File); + var message = await fileInstruct.VaryImage(input.Provider, input.Model, input.File, input.AgentId); imageViewModel.Content = message.Content; imageViewModel.Images = message.GeneratedImages.Select(x => ImageViewModel.ToViewModel(x)).ToList(); @@ -188,7 +188,7 @@ public async Task ImageVariation([FromBody] ImageVaria [HttpPost("/instruct/image-variation/upload")] public async Task ImageVariation(IFormFile file, [FromForm] string? provider = null, - [FromForm] string? model = null, [FromForm] List? states = null) + [FromForm] string? model = null, [FromForm] List? states = null, [FromForm] string? agentId = null) { var state = _services.GetRequiredService(); states?.ForEach(x => state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); @@ -203,7 +203,7 @@ public async Task ImageVariation(IFormFile file, [From var completion = CompletionProvider.GetImageCompletion(_services, provider: provider ?? "openai", model: model ?? "dall-e-2"); var message = await completion.GetImageVariation(new Agent() { - Id = Guid.Empty.ToString() + Id = agentId ?? Guid.Empty.ToString() }, new RoleDialogModel(AgentRole.User, string.Empty), stream, file.FileName); imageViewModel.Content = message.Content; @@ -235,7 +235,7 @@ public async Task ImageEdit([FromBody] ImageEditReques { return new ImageGenerationViewModel { Message = "Error! Cannot find a valid image file!" }; } - var message = await fileInstruct.EditImage(input.Provider, input.Model, input.Text, input.File); + var message = await fileInstruct.EditImage(input.Provider, input.Model, input.Text, input.File, input.AgentId); imageViewModel.Content = message.Content; imageViewModel.Images = message.GeneratedImages.Select(x => ImageViewModel.ToViewModel(x)).ToList(); return imageViewModel; @@ -251,7 +251,7 @@ public async Task ImageEdit([FromBody] ImageEditReques [HttpPost("/instruct/image-edit/upload")] public async Task ImageEdit(IFormFile file, [FromForm] string text, [FromForm] string? provider = null, - [FromForm] string? model = null, [FromForm] List? states = null) + [FromForm] string? model = null, [FromForm] List? states = null, [FromForm] string? agentId = null) { var fileInstruct = _services.GetRequiredService(); var state = _services.GetRequiredService(); @@ -267,7 +267,7 @@ public async Task ImageEdit(IFormFile file, [FromForm] var completion = CompletionProvider.GetImageCompletion(_services, provider: provider ?? "openai", model: model ?? "dall-e-2"); var message = await completion.GetImageEdits(new Agent() { - Id = Guid.Empty.ToString() + Id = agentId ?? Guid.Empty.ToString() }, new RoleDialogModel(AgentRole.User, text), stream, file.FileName); imageViewModel.Content = message.Content; @@ -301,7 +301,7 @@ public async Task ImageMaskEdit([FromBody] ImageMaskEd { return new ImageGenerationViewModel { Message = "Error! Cannot find a valid image or mask!" }; } - var message = await fileInstruct.EditImage(input.Provider, input.Model, input.Text, image, mask); + var message = await fileInstruct.EditImage(input.Provider, input.Model, input.Text, image, mask, input.AgentId); imageViewModel.Content = message.Content; imageViewModel.Images = message.GeneratedImages.Select(x => ImageViewModel.ToViewModel(x)).ToList(); return imageViewModel; @@ -317,7 +317,7 @@ public async Task ImageMaskEdit([FromBody] ImageMaskEd [HttpPost("/instruct/image-mask-edit/upload")] public async Task ImageMaskEdit(IFormFile image, IFormFile mask, [FromForm] string text, [FromForm] string? provider = null, - [FromForm] string? model = null, [FromForm] List? states = null) + [FromForm] string? model = null, [FromForm] List? states = null, [FromForm] string? agentId = null) { var fileInstruct = _services.GetRequiredService(); var state = _services.GetRequiredService(); @@ -337,7 +337,7 @@ public async Task ImageMaskEdit(IFormFile image, IForm var completion = CompletionProvider.GetImageCompletion(_services, provider: provider ?? "openai", model: model ?? "dall-e-2"); var message = await completion.GetImageEdits(new Agent() { - Id = Guid.Empty.ToString() + Id = agentId ?? Guid.Empty.ToString() }, new RoleDialogModel(AgentRole.User, text), imageStream, image.FileName, maskStream, mask.FileName); imageViewModel.Content = message.Content; @@ -368,7 +368,7 @@ public async Task PdfCompletion([FromBody] MultiModalReq try { var fileInstruct = _services.GetRequiredService(); - var content = await fileInstruct.ReadPdf(input.Provider, input.Model, input.ModelId, input.Text, input.Files); + var content = await fileInstruct.ReadPdf(input.Provider, input.Model, input.ModelId, input.Text, input.Files, input.AgentId); viewModel.Content = content; return viewModel; } @@ -383,7 +383,7 @@ public async Task PdfCompletion([FromBody] MultiModalReq [HttpPost("/instruct/pdf-completion/upload")] public async Task PdfCompletion(IFormFile file, [FromForm] string text, [FromForm] string? provider = null, - [FromForm] string? model = null, [FromForm] string? modelId = null, [FromForm] List? states = null) + [FromForm] string? model = null, [FromForm] string? modelId = null, [FromForm] List? states = null, [FromForm] string? agentId = null) { var state = _services.GetRequiredService(); states?.ForEach(x => state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); @@ -398,7 +398,7 @@ public async Task PdfCompletion(IFormFile file, [FromFor }; var fileInstruct = _services.GetRequiredService(); - var content = await fileInstruct.ReadPdf(provider, model, modelId, text, files); + var content = await fileInstruct.ReadPdf(provider, model, modelId, text, files, agentId); viewModel.Content = content; return viewModel; } diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Instructs/InstructBaseRequest.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Instructs/InstructBaseRequest.cs index 39a6439d9..88f011be6 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Instructs/InstructBaseRequest.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Instructs/InstructBaseRequest.cs @@ -13,6 +13,9 @@ public class InstructBaseRequest [JsonPropertyName("model_id")] public virtual string? ModelId { get; set; } = null; + [JsonPropertyName("agent_id")] + public virtual string? AgentId { get; set; } + [JsonPropertyName("states")] public List States { get; set; } = new(); } diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/DialogMongoElement.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/DialogMongoElement.cs index 53c09d4ad..87022130c 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/DialogMongoElement.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/DialogMongoElement.cs @@ -42,6 +42,7 @@ public static DialogElement ToDomainElement(DialogMongoElement dialog) } } +[BsonIgnoreExtraElements(Inherited = true)] public class DialogMetaDataMongoElement { public string Role { get; set; } = default!; @@ -50,7 +51,7 @@ public class DialogMetaDataMongoElement public string MessageType { get; set; } = default!; public string? FunctionName { get; set; } public string? SenderId { get; set; } - public DateTime CreatedTime { get; set; } + public DateTime CreateTime { get; set; } public static DialogMetaData ToDomainElement(DialogMetaDataMongoElement meta) { @@ -62,7 +63,7 @@ public static DialogMetaData ToDomainElement(DialogMetaDataMongoElement meta) MessageType = meta.MessageType, FunctionName = meta.FunctionName, SenderId = meta.SenderId, - CreatedTime = meta.CreatedTime, + CreatedTime = meta.CreateTime, }; } @@ -76,7 +77,7 @@ public static DialogMetaDataMongoElement ToMongoElement(DialogMetaData meta) MessageType = meta.MessageType, FunctionName = meta.FunctionName, SenderId = meta.SenderId, - CreatedTime = meta.CreatedTime, + CreateTime = meta.CreatedTime, }; } } diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs index 91e668f31..4d7f76a46 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs @@ -48,10 +48,11 @@ private string GetDatabaseName(string mongoDbConnectionString) private IMongoDatabase Database => _mongoClient.GetDatabase(_mongoDbDatabaseName); + #region Private methods private bool CollectionExists(IMongoDatabase database, string collectionName) { var filter = Builders.Filter.Eq("name", collectionName); - var collections = database.ListCollections(new ListCollectionsOptions { Filter = filter }); + var collections = database.ListCollectionNames(new ListCollectionNamesOptions { Filter = filter }).ToList(); return collections.Any(); } @@ -60,9 +61,11 @@ private IMongoCollection GetCollectionOrCreate(string name if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException($"The collection {name} cannot be empty."); - string collectionName = $"{_collectionPrefix}_{name}"; + var collectionName = $"{_collectionPrefix}_{name}"; if (!CollectionExists(Database, collectionName)) + { Database.CreateCollection(collectionName); + } var collection = Database.GetCollection(collectionName); return collection; @@ -134,6 +137,7 @@ private IMongoCollection CreateStateLogIndex() return collection; } #endregion + #endregion public IMongoCollection Agents => GetCollectionOrCreate("Agents"); diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs index 46e378d59..7d45e9729 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs @@ -534,7 +534,7 @@ public List TruncateConversation(string conversationId, string messageId var truncatedDialogs = foundDialog.Dialogs.Where((x, idx) => idx < foundIdx).ToList(); // Handle truncated states - var refTime = foundDialog.Dialogs.ElementAt(foundIdx).MetaData.CreatedTime; + var refTime = foundDialog.Dialogs.ElementAt(foundIdx).MetaData.CreateTime; var stateFilter = Builders.Filter.Eq(x => x.ConversationId, conversationId); var foundStates = _dc.ConversationStates.Find(stateFilter).FirstOrDefault();