From cf08261afbd8dab6f2dc3cdfa7acaa9a4e3098ad Mon Sep 17 00:00:00 2001 From: Deep Blue Date: Mon, 27 Nov 2023 15:00:26 -0600 Subject: [PATCH] RichMessageBase and Welcome message. --- .../Conversations/ConversationHookBase.cs | 5 ++++ .../Conversations/IConversationHook.cs | 8 ++++++ .../Conversations/IConversationService.cs | 1 + .../Messaging/IRichMessage.cs | 1 + .../Models/RichContent/QuickReplyMessage.cs | 4 +-- .../Template/ButtonTemplateMessage.cs | 6 ++-- .../Template/CouponTemplateMessage.cs | 12 ++++---- .../Template/MultiSelectTemplateMessage.cs | 4 +-- .../Template/ProductTemplateMessage.cs | 1 + .../Template/TemplateMessageBase.cs | 5 +++- .../Models/RichContent/TextMessage.cs | 4 +-- .../Messaging/RichMessageBase.cs | 11 ++++++++ .../Services/ConversationService.cs | 14 ++++++++++ .../Controllers/ConversationController.cs | 7 +++++ .../ViewModels/Agents/AgentViewModel.cs | 9 ++++++ .../BotSharp.Plugin.AzureOpenAI.csproj | 4 +-- .../BotSharp.Plugin.ChatHub.csproj | 2 +- .../Hooks/ChatHubConversationHook.cs | 25 +++++++++++++++++ .../BotSharp.Plugin.ChatHub/SignalRHub.cs | 22 --------------- .../BotSharp.Plugin.ChatbotUI.csproj | 2 +- .../BotSharp.Plugin.GoogleAI.csproj | 2 +- .../BotSharp.Plugin.MetaAI.csproj | 2 +- .../BotSharp.Plugin.MetaMessenger.csproj | 2 +- .../MessagingModels/AttachmentMessage.cs | 2 ++ .../BotSharp.Plugin.TelegramBots.csproj | 2 +- .../BotSharp.Plugin.WeChat.csproj | 2 +- .../templates/welcome.liquid | 8 ++++++ src/web-live-chat/package-lock.json | 4 +-- src/web-live-chat/src/lib/helpers/typedefs.js | 13 +++++++++ .../src/lib/services/agent-service.js | 20 +++++++++++++ .../src/lib/services/api-endpoints.js | 1 + .../src/lib/services/conversation-service.js | 11 ++++++++ .../src/routes/chat/[agentId]/+page.svelte | 9 ++++-- .../[agentId]/[conversationId]/+page.svelte | 28 +++++++++++++++++-- .../[conversationId]/chat-box.svelte | 15 ++++++---- 35 files changed, 209 insertions(+), 59 deletions(-) create mode 100644 src/Infrastructure/BotSharp.Abstraction/Messaging/RichMessageBase.cs create mode 100644 src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/welcome.liquid create mode 100644 src/web-live-chat/src/lib/services/agent-service.js diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs index 3d82500c4..230a3f2da 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs @@ -81,4 +81,9 @@ public virtual Task OnConversationInitialized(Conversation conversation) { return Task.CompletedTask; } + + public virtual Task OnUserAgentConnectedInitially(Conversation conversation) + { + return Task.CompletedTask; + } } diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs index 890fca04d..e25314387 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationHook.cs @@ -10,6 +10,14 @@ public interface IConversationHook Conversation Conversation { get; } IConversationHook SetConversation(Conversation conversation); + /// + /// Triggered when user connects with agent first time. + /// This hook is the good timing to show welcome infomation. + /// + /// + /// + Task OnUserAgentConnectedInitially(Conversation conversation); + /// /// Triggered once for every new conversation. /// diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs index c475d6a5c..7774cf50a 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs @@ -5,6 +5,7 @@ public interface IConversationService IConversationStateService States { get; } string ConversationId { get; } Task NewConversation(Conversation conversation); + Task MarkConnectionReady(string conversationId); void SetConversationId(string conversationId, List states); Task GetConversation(string id); Task> GetConversations(); diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/IRichMessage.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/IRichMessage.cs index 0fce3f4c8..3f61bc8d9 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/IRichMessage.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/IRichMessage.cs @@ -2,5 +2,6 @@ namespace BotSharp.Abstraction.Messaging; public interface IRichMessage { + string Type { get; } string Text { 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 b0081c81d..4fb1bcdb0 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/QuickReplyMessage.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/QuickReplyMessage.cs @@ -1,8 +1,8 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent { - public class QuickReplyMessage : IRichMessage + public class QuickReplyMessage : RichMessageBase, IRichMessage { - public string Text { get; set; } = string.Empty; + public override string Type => "quick reply"; [JsonPropertyName("quick_replies")] public List QuickReplies { get; set; } = new List(); 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 2ec5464eb..93af426a1 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ButtonTemplateMessage.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ButtonTemplateMessage.cs @@ -3,12 +3,12 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template /// /// https://developers.facebook.com/docs/messenger-platform/send-messages/buttons /// - public class ButtonTemplateMessage : IRichMessage + public class ButtonTemplateMessage : RichMessageBase, IRichMessage, ITemplateMessage { - public string Text { get; set; } = string.Empty; + public override string Type => "template"; [JsonPropertyName("template_type")] - public string TemplateType => "button"; + public override string TemplateType => "button"; public List Buttons { get; set; } = new List(); } diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/CouponTemplateMessage.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/CouponTemplateMessage.cs index 8fb74efdb..d4ab5fb06 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/CouponTemplateMessage.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/CouponTemplateMessage.cs @@ -4,16 +4,18 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template; /// Coupon Template /// https://developers.facebook.com/docs/messenger-platform/send-messages/template/coupon /// -public class CouponTemplateMessage : IRichMessage, ITemplateMessage +public class CouponTemplateMessage : RichMessageBase, IRichMessage, ITemplateMessage { + public override string Type => "template"; + + [JsonPropertyName("template_type")] + public override string TemplateType => "coupon"; + [JsonIgnore] - public string Text { get; set; } + public override string Text { get; set; } public string Title { get; set; } public string Subtitle { get; set; } - [JsonPropertyName("template_type")] - public string TemplateType => "coupon"; - [JsonPropertyName("coupon_code")] public string CouponCode { get; set; } diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/MultiSelectTemplateMessage.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/MultiSelectTemplateMessage.cs index df8e11834..a7b0e5ff3 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/MultiSelectTemplateMessage.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/MultiSelectTemplateMessage.cs @@ -1,8 +1,8 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template { - public class MultiSelectTemplateMessage : IRichMessage + public class MultiSelectTemplateMessage : RichMessageBase, IRichMessage { - public string Text { get; set; } = string.Empty; + public override string Type => "template"; [JsonPropertyName("template_type")] public string TemplateType => "multi-select"; diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ProductTemplateMessage.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ProductTemplateMessage.cs index bfbdcbb35..ccdd66a56 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ProductTemplateMessage.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ProductTemplateMessage.cs @@ -2,6 +2,7 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template; public class ProductTemplateMessage : TemplateMessageBase, IRichMessage { + [JsonPropertyName("template_type")] public override string TemplateType => "product"; } diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/TemplateMessageBase.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/TemplateMessageBase.cs index b2d568cc9..ab2ecd66f 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/TemplateMessageBase.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/TemplateMessageBase.cs @@ -1,12 +1,15 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template { - public class TemplateMessageBase + public class TemplateMessageBase : RichMessageBase { [JsonIgnore] public string Text { get; set; } + public override string Type => "template"; + [JsonPropertyName("template_type")] public virtual string TemplateType => string.Empty; + public T[] Elements { 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 dfb611d3b..a615318ed 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/TextMessage.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/TextMessage.cs @@ -1,8 +1,8 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent; -public class TextMessage : IRichMessage +public class TextMessage : RichMessageBase, IRichMessage { - public string Text { get; set; } = string.Empty; + public string Type => "text"; public TextMessage(string text) { diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/RichMessageBase.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/RichMessageBase.cs new file mode 100644 index 000000000..39c39b80c --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/RichMessageBase.cs @@ -0,0 +1,11 @@ +namespace BotSharp.Abstraction.Messaging; + +public class RichMessageBase +{ + public virtual string Type { get; } + + public virtual string Text { get; set; } + + [JsonPropertyName("template_type")] + public virtual string TemplateType { get; } +} diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs index 92084c781..874690b51 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs @@ -84,6 +84,9 @@ public async Task NewConversation(Conversation sess) var hooks = _services.GetServices().ToList(); foreach (var hook in hooks) { + // If user connect agent first time + await hook.OnUserAgentConnectedInitially(sess); + await hook.OnConversationInitialized(record); } @@ -115,4 +118,15 @@ public void SetConversationId(string conversationId, List states) _state.Load(_conversationId); states.ForEach(x => _state.SetState(x.Split('=')[0], x.Split('=')[1])); } + + public async Task MarkConnectionReady(string conversationId) + { + var hooks = _services.GetServices(); + var conv = await GetConversation(conversationId); + foreach (var hook in hooks) + { + // Need to check if user connected with agent is the first time. + await hook.OnUserAgentConnectedInitially(conv); + } + } } diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs index dde374821..97b10cd22 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs @@ -41,6 +41,13 @@ public async Task NewConversation([FromRoute] string agen return ConversationViewModel.FromSession(conv); } + [HttpPatch("/conversation/{conversationId}/ready")] + public async Task ReadyToInteractive([FromRoute] string conversationId) + { + var service = _services.GetRequiredService(); + await service.MarkConnectionReady(conversationId); + } + [HttpGet("/conversations/{agentId}")] public async Task> GetConversations() { diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs index 3ff1f0694..2ef67efd7 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Agents/AgentViewModel.cs @@ -1,6 +1,7 @@ using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Functions.Models; using BotSharp.Abstraction.Routing.Models; +using System.Text.Json.Serialization; namespace BotSharp.OpenAPI.ViewModels.Agents; @@ -15,12 +16,20 @@ public class AgentViewModel public List Responses { get; set; } public List Samples { get; set; } public bool IsPublic { get; set; } + + [JsonPropertyName("allow_routing")] public bool AllowRouting { get; set; } public bool Disabled { get; set; } public List Profiles { get; set; } + + [JsonPropertyName("routing_rules")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public List RoutingRules { get; set; } + [JsonPropertyName("created_datetime")] public DateTime CreatedDateTime { get; set; } + + [JsonPropertyName("updated_datetime")] public DateTime UpdatedDateTime { get; set; } public static AgentViewModel FromAgent(Agent agent) diff --git a/src/Plugins/BotSharp.Plugin.AzureOpenAI/BotSharp.Plugin.AzureOpenAI.csproj b/src/Plugins/BotSharp.Plugin.AzureOpenAI/BotSharp.Plugin.AzureOpenAI.csproj index 03f701cdf..812050027 100644 --- a/src/Plugins/BotSharp.Plugin.AzureOpenAI/BotSharp.Plugin.AzureOpenAI.csproj +++ b/src/Plugins/BotSharp.Plugin.AzureOpenAI/BotSharp.Plugin.AzureOpenAI.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -6,7 +6,7 @@ $(LangVersion) $(BotSharpVersion) $(GeneratePackageOnBuild) - True + $(GenerateDocumentationFile) diff --git a/src/Plugins/BotSharp.Plugin.ChatHub/BotSharp.Plugin.ChatHub.csproj b/src/Plugins/BotSharp.Plugin.ChatHub/BotSharp.Plugin.ChatHub.csproj index 487a2e95a..34a924d42 100644 --- a/src/Plugins/BotSharp.Plugin.ChatHub/BotSharp.Plugin.ChatHub.csproj +++ b/src/Plugins/BotSharp.Plugin.ChatHub/BotSharp.Plugin.ChatHub.csproj @@ -7,7 +7,7 @@ $(LangVersion) $(BotSharpVersion) $(GeneratePackageOnBuild) - True + $(GenerateDocumentationFile) diff --git a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/ChatHubConversationHook.cs b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/ChatHubConversationHook.cs index 4fadba6f6..472b20b14 100644 --- a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/ChatHubConversationHook.cs +++ b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/ChatHubConversationHook.cs @@ -1,3 +1,4 @@ +using BotSharp.Abstraction.Messaging; using Microsoft.AspNetCore.SignalR; namespace BotSharp.Plugin.ChatHub.Hooks; @@ -14,6 +15,30 @@ public ChatHubConversationHook(IServiceProvider services, _chatHub = chatHub; } + public override async Task OnUserAgentConnectedInitially(Conversation conversation) + { + var agentService = _services.GetService(); + var agent = await agentService.LoadAgent(conversation.AgentId); + + // Check if the Welcome template exists. + var welcomeTemplate = agent.Templates.FirstOrDefault(x => x.Name == "welcome"); + if (welcomeTemplate != null) + { + var messages = JsonSerializer.Deserialize(welcomeTemplate.Content, new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }); + + foreach (var message in messages) + { + await Task.Delay(300); + await OnResponseGenerated(new RoleDialogModel(AgentRole.Assistant, message.Text)); + } + } + + await base.OnUserAgentConnectedInitially(conversation); + } + public override async Task OnConversationInitialized(Conversation conversation) { var userService = _services.GetRequiredService(); diff --git a/src/Plugins/BotSharp.Plugin.ChatHub/SignalRHub.cs b/src/Plugins/BotSharp.Plugin.ChatHub/SignalRHub.cs index ea18acb73..d01d2b089 100644 --- a/src/Plugins/BotSharp.Plugin.ChatHub/SignalRHub.cs +++ b/src/Plugins/BotSharp.Plugin.ChatHub/SignalRHub.cs @@ -17,28 +17,6 @@ public SignalRHub(IServiceProvider services, _user = user; } - public async Task OnMessageReceivedFromClient(string message) - { - // await Clients.User(_user.Id).SendAsync("ReceiveMessage", message); - } - - /// - /// Received message from client - /// - /// - /// - /// - public async Task SendMessage(string user, string message) - { - // await Clients.User(_user.Id).SendAsync("ReceiveMessage", message); - } - - public async Task SendMessageToCaller(string user, string message) - => await Clients.Caller.SendAsync("ReceiveMessage", user, message); - - public async Task SendMessageToGroup(string user, string message) - => await Clients.Group("SignalR Users").SendAsync("ReceiveMessage", user, message); - public override Task OnConnectedAsync() { Console.WriteLine($"SignalR Hub: {Context.UserIdentifier} connected in {Context.ConnectionId} [{DateTime.Now}]"); diff --git a/src/Plugins/BotSharp.Plugin.ChatbotUI/BotSharp.Plugin.ChatbotUI.csproj b/src/Plugins/BotSharp.Plugin.ChatbotUI/BotSharp.Plugin.ChatbotUI.csproj index 8d96e352f..39ea06b20 100644 --- a/src/Plugins/BotSharp.Plugin.ChatbotUI/BotSharp.Plugin.ChatbotUI.csproj +++ b/src/Plugins/BotSharp.Plugin.ChatbotUI/BotSharp.Plugin.ChatbotUI.csproj @@ -6,7 +6,7 @@ $(LangVersion) $(BotSharpVersion) $(GeneratePackageOnBuild) - True + $(GenerateDocumentationFile) diff --git a/src/Plugins/BotSharp.Plugin.GoogleAI/BotSharp.Plugin.GoogleAI.csproj b/src/Plugins/BotSharp.Plugin.GoogleAI/BotSharp.Plugin.GoogleAI.csproj index 12a2a4170..02eef1902 100644 --- a/src/Plugins/BotSharp.Plugin.GoogleAI/BotSharp.Plugin.GoogleAI.csproj +++ b/src/Plugins/BotSharp.Plugin.GoogleAI/BotSharp.Plugin.GoogleAI.csproj @@ -6,7 +6,7 @@ $(LangVersion) $(BotSharpVersion) $(GeneratePackageOnBuild) - True + $(GenerateDocumentationFile) diff --git a/src/Plugins/BotSharp.Plugin.MetaAI/BotSharp.Plugin.MetaAI.csproj b/src/Plugins/BotSharp.Plugin.MetaAI/BotSharp.Plugin.MetaAI.csproj index 7bf6a42ed..2a6171f76 100644 --- a/src/Plugins/BotSharp.Plugin.MetaAI/BotSharp.Plugin.MetaAI.csproj +++ b/src/Plugins/BotSharp.Plugin.MetaAI/BotSharp.Plugin.MetaAI.csproj @@ -6,7 +6,7 @@ $(LangVersion) $(BotSharpVersion) $(GeneratePackageOnBuild) - True + $(GenerateDocumentationFile) diff --git a/src/Plugins/BotSharp.Plugin.MetaMessenger/BotSharp.Plugin.MetaMessenger.csproj b/src/Plugins/BotSharp.Plugin.MetaMessenger/BotSharp.Plugin.MetaMessenger.csproj index d4ce78509..c247a41f2 100644 --- a/src/Plugins/BotSharp.Plugin.MetaMessenger/BotSharp.Plugin.MetaMessenger.csproj +++ b/src/Plugins/BotSharp.Plugin.MetaMessenger/BotSharp.Plugin.MetaMessenger.csproj @@ -5,7 +5,7 @@ $(LangVersion) $(BotSharpVersion) $(GeneratePackageOnBuild) - GenerateDocumentationFile + $(GenerateDocumentationFile) diff --git a/src/Plugins/BotSharp.Plugin.MetaMessenger/MessagingModels/AttachmentMessage.cs b/src/Plugins/BotSharp.Plugin.MetaMessenger/MessagingModels/AttachmentMessage.cs index 08aaad34c..68e3336a4 100644 --- a/src/Plugins/BotSharp.Plugin.MetaMessenger/MessagingModels/AttachmentMessage.cs +++ b/src/Plugins/BotSharp.Plugin.MetaMessenger/MessagingModels/AttachmentMessage.cs @@ -10,4 +10,6 @@ public class AttachmentMessage : IRichMessage [JsonPropertyName("attachment")] public AttachmentBody Attachment { get; set; } + + public string Type => "template"; } diff --git a/src/Plugins/BotSharp.Plugin.TelegramBots/BotSharp.Plugin.TelegramBots.csproj b/src/Plugins/BotSharp.Plugin.TelegramBots/BotSharp.Plugin.TelegramBots.csproj index 55b5db95f..480ebabc3 100644 --- a/src/Plugins/BotSharp.Plugin.TelegramBots/BotSharp.Plugin.TelegramBots.csproj +++ b/src/Plugins/BotSharp.Plugin.TelegramBots/BotSharp.Plugin.TelegramBots.csproj @@ -6,7 +6,7 @@ $(LangVersion) $(BotSharpVersion) $(GeneratePackageOnBuild) - True + $(GenerateDocumentationFile) diff --git a/src/Plugins/BotSharp.Plugin.WeChat/BotSharp.Plugin.WeChat.csproj b/src/Plugins/BotSharp.Plugin.WeChat/BotSharp.Plugin.WeChat.csproj index e08f0f137..8c06e96fb 100644 --- a/src/Plugins/BotSharp.Plugin.WeChat/BotSharp.Plugin.WeChat.csproj +++ b/src/Plugins/BotSharp.Plugin.WeChat/BotSharp.Plugin.WeChat.csproj @@ -5,7 +5,7 @@ $(LangVersion) $(BotSharpVersion) $(GeneratePackageOnBuild) - True + $(GenerateDocumentationFile) diff --git a/src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/welcome.liquid b/src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/welcome.liquid new file mode 100644 index 000000000..6a0b27809 --- /dev/null +++ b/src/WebStarter/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/welcome.liquid @@ -0,0 +1,8 @@ +[ + { + "text": "Hello, I'm an AI assistant that help you do variety of tasks." + }, + { + "text": "How can I help you today?" + } +] \ No newline at end of file diff --git a/src/web-live-chat/package-lock.json b/src/web-live-chat/package-lock.json index cc5be5bf6..aa704d782 100644 --- a/src/web-live-chat/package-lock.json +++ b/src/web-live-chat/package-lock.json @@ -1,11 +1,11 @@ { - "name": "embedded-chat", + "name": "web-live-chat", "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "embedded-chat", + "name": "web-live-chat", "version": "0.1.0", "dependencies": { "@microsoft/signalr": "^8.0.0", diff --git a/src/web-live-chat/src/lib/helpers/typedefs.js b/src/web-live-chat/src/lib/helpers/typedefs.js index e5aaf0c8f..085987c74 100644 --- a/src/web-live-chat/src/lib/helpers/typedefs.js +++ b/src/web-live-chat/src/lib/helpers/typedefs.js @@ -16,6 +16,19 @@ * @property {string} assembly - The plugin assembly. */ +/** + * @typedef {Object} AgentWelcomeInfo + * @property {string[]} messages - The welcome messages in Rich content format. + */ + +/** + * @typedef {Object} AgentModel + * @property {string} id - Agent Id. + * @property {string} name - Agent name. + * @property {string} description - Agent description. + * @property {AgentWelcomeInfo} welcome_info - Welcome information. + */ + /** * @typedef {Object} ConversationModel * @property {string} id - The conversation id. diff --git a/src/web-live-chat/src/lib/services/agent-service.js b/src/web-live-chat/src/lib/services/agent-service.js new file mode 100644 index 000000000..3b58ce281 --- /dev/null +++ b/src/web-live-chat/src/lib/services/agent-service.js @@ -0,0 +1,20 @@ +import { agentListUrl, agentDetailUrl } from '$lib/services/api-endpoints.js'; +import axios from 'axios'; + +/** + * @returns {Promise} + */ +export async function getAgents() { + const response = await axios.get(agentListUrl); + return response.data; +} + +/** + * @param {string} id + * @returns {Promise} + */ +export async function getAgent(id) { + let url = agentDetailUrl.replace("{id}", id); + const response = await axios.get(url); + return response.data; +} diff --git a/src/web-live-chat/src/lib/services/api-endpoints.js b/src/web-live-chat/src/lib/services/api-endpoints.js index 4948b1bd6..421b2fdbb 100644 --- a/src/web-live-chat/src/lib/services/api-endpoints.js +++ b/src/web-live-chat/src/lib/services/api-endpoints.js @@ -14,6 +14,7 @@ export const agentDetailUrl = `${host}/agent/{id}`; // conversation export const conversationInitUrl = `${host}/conversation/{agentId}` +export const conversationReadyUrl = `${host}/conversation/{conversationId}/ready` export const conversationMessageUrl = `${host}/conversation/{agentId}/{conversationId}` export const conversationsUrl = `${host}/conversations/{agentId}` export const dialogsUrl = `${host}/conversation/{conversationId}/dialogs` diff --git a/src/web-live-chat/src/lib/services/conversation-service.js b/src/web-live-chat/src/lib/services/conversation-service.js index 38e96a508..d6158c76f 100644 --- a/src/web-live-chat/src/lib/services/conversation-service.js +++ b/src/web-live-chat/src/lib/services/conversation-service.js @@ -2,6 +2,7 @@ import { conversationInitUrl, conversationMessageUrl, dialogsUrl, + conversationReadyUrl, } from './api-endpoints.js'; import axios from 'axios'; @@ -17,6 +18,16 @@ export async function newConversation(agentId) { return response.data; } +/** + * Coversation is ready + * @param {string} conversationId + */ +export async function conversationReady(conversationId) { + let url = conversationReadyUrl.replace("{conversationId}", conversationId); + const response = await axios.patch(url, {}); + return response.data; +} + /** * Get dialog history * @param {string} conversationId diff --git a/src/web-live-chat/src/routes/chat/[agentId]/+page.svelte b/src/web-live-chat/src/routes/chat/[agentId]/+page.svelte index caab5640b..9492b4ab9 100644 --- a/src/web-live-chat/src/routes/chat/[agentId]/+page.svelte +++ b/src/web-live-chat/src/routes/chat/[agentId]/+page.svelte @@ -13,7 +13,8 @@ /** @type {import('$typedefs').ConversationModel} */ let conversation; let conversationId = "undefined"; - let agentId = "undefined"; + + let agentId = params.agentId; onMount(async () => { let userToken = ""; @@ -25,9 +26,11 @@ userToken = $page.url.searchParams.get('token') ?? "unauthorized"; } setAuthorization(userToken); - conversation = await newConversation(params.agentId); + + // new conversation + conversation = await newConversation(agentId); conversationId = conversation.id; - agentId = params.agentId; + window.location.href = `/chat/${agentId}/${conversationId}?token=${userToken}`; }); diff --git a/src/web-live-chat/src/routes/chat/[agentId]/[conversationId]/+page.svelte b/src/web-live-chat/src/routes/chat/[agentId]/[conversationId]/+page.svelte index 35f815695..43ccc78e8 100644 --- a/src/web-live-chat/src/routes/chat/[agentId]/[conversationId]/+page.svelte +++ b/src/web-live-chat/src/routes/chat/[agentId]/[conversationId]/+page.svelte @@ -1,5 +1,29 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/web-live-chat/src/routes/chat/[agentId]/[conversationId]/chat-box.svelte b/src/web-live-chat/src/routes/chat/[agentId]/[conversationId]/chat-box.svelte index 640e454b5..a3707493d 100644 --- a/src/web-live-chat/src/routes/chat/[agentId]/[conversationId]/chat-box.svelte +++ b/src/web-live-chat/src/routes/chat/[agentId]/[conversationId]/chat-box.svelte @@ -13,10 +13,9 @@ import { page } from '$app/stores'; import { onMount } from 'svelte'; import Link from 'svelte-link'; - import { myInfo } from '$lib/services/auth-service.js'; - import { signalr } from '$lib/services/signalr-service.js'; - import { sendMessageToHub, GetDialogs } from '$lib/services/conversation-service.js'; import { setAuthorization } from '$lib/helpers/http'; + import { signalr } from '$lib/services/signalr-service.js'; + import { sendMessageToHub, GetDialogs, conversationReady } from '$lib/services/conversation-service.js'; const options = { scrollbars: { @@ -32,9 +31,12 @@ const params = $page.params; let text = "Hi"; + + /** @type {import('$typedefs').AgentModel} */ + export let agent; /** @type {import('$typedefs').UserModel} */ - let currentUser; + export let currentUser; // @ts-ignore let scrollbar; @@ -46,14 +48,15 @@ const token = $page.url.searchParams.get('token') ?? "unauthorized"; setAuthorization(token); - currentUser = await myInfo(token); - dialogs = await GetDialogs(params.conversationId); + signalr.onMessageReceivedFromClient = onMessageReceivedFromClient; signalr.onMessageReceivedFromCsr = onMessageReceivedFromCsr; signalr.onMessageReceivedFromAssistant = onMessageReceivedFromAssistant; await signalr.start(); + await conversationReady(params.conversationId); + const scrollElements = document.querySelectorAll('.scrollbar'); scrollElements.forEach((item) => { scrollbar = OverlayScrollbars(item, options);