RichMessageBase and Welcome message.
This commit is contained in:
parent
b7d9469cf1
commit
cf08261afb
|
|
@ -81,4 +81,9 @@ public abstract class ConversationHookBase : IConversationHook
|
||||||
{
|
{
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual Task OnUserAgentConnectedInitially(Conversation conversation)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,14 @@ public interface IConversationHook
|
||||||
Conversation Conversation { get; }
|
Conversation Conversation { get; }
|
||||||
IConversationHook SetConversation(Conversation conversation);
|
IConversationHook SetConversation(Conversation conversation);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Triggered when user connects with agent first time.
|
||||||
|
/// This hook is the good timing to show welcome infomation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="conversation"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task OnUserAgentConnectedInitially(Conversation conversation);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Triggered once for every new conversation.
|
/// Triggered once for every new conversation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ public interface IConversationService
|
||||||
IConversationStateService States { get; }
|
IConversationStateService States { get; }
|
||||||
string ConversationId { get; }
|
string ConversationId { get; }
|
||||||
Task<Conversation> NewConversation(Conversation conversation);
|
Task<Conversation> NewConversation(Conversation conversation);
|
||||||
|
Task MarkConnectionReady(string conversationId);
|
||||||
void SetConversationId(string conversationId, List<string> states);
|
void SetConversationId(string conversationId, List<string> states);
|
||||||
Task<Conversation> GetConversation(string id);
|
Task<Conversation> GetConversation(string id);
|
||||||
Task<List<Conversation>> GetConversations();
|
Task<List<Conversation>> GetConversations();
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,6 @@ namespace BotSharp.Abstraction.Messaging;
|
||||||
|
|
||||||
public interface IRichMessage
|
public interface IRichMessage
|
||||||
{
|
{
|
||||||
|
string Type { get; }
|
||||||
string Text { get; set; }
|
string Text { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
namespace BotSharp.Abstraction.Messaging.Models.RichContent
|
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")]
|
[JsonPropertyName("quick_replies")]
|
||||||
public List<QuickReplyElement> QuickReplies { get; set; } = new List<QuickReplyElement>();
|
public List<QuickReplyElement> QuickReplies { get; set; } = new List<QuickReplyElement>();
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,12 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// https://developers.facebook.com/docs/messenger-platform/send-messages/buttons
|
/// https://developers.facebook.com/docs/messenger-platform/send-messages/buttons
|
||||||
/// </summary>
|
/// </summary>
|
||||||
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")]
|
[JsonPropertyName("template_type")]
|
||||||
public string TemplateType => "button";
|
public override string TemplateType => "button";
|
||||||
public List<ButtonElement> Buttons { get; set; } = new List<ButtonElement>();
|
public List<ButtonElement> Buttons { get; set; } = new List<ButtonElement>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,17 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template;
|
||||||
/// Coupon Template
|
/// Coupon Template
|
||||||
/// https://developers.facebook.com/docs/messenger-platform/send-messages/template/coupon
|
/// https://developers.facebook.com/docs/messenger-platform/send-messages/template/coupon
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CouponTemplateMessage : IRichMessage, ITemplateMessage
|
public class CouponTemplateMessage : RichMessageBase, IRichMessage, ITemplateMessage
|
||||||
{
|
{
|
||||||
[JsonIgnore]
|
public override string Type => "template";
|
||||||
public string Text { get; set; }
|
|
||||||
public string Title { get; set; }
|
|
||||||
public string Subtitle { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("template_type")]
|
[JsonPropertyName("template_type")]
|
||||||
public string TemplateType => "coupon";
|
public override string TemplateType => "coupon";
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public override string Text { get; set; }
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string Subtitle { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("coupon_code")]
|
[JsonPropertyName("coupon_code")]
|
||||||
public string CouponCode { get; set; }
|
public string CouponCode { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template
|
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")]
|
[JsonPropertyName("template_type")]
|
||||||
public string TemplateType => "multi-select";
|
public string TemplateType => "multi-select";
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template;
|
||||||
|
|
||||||
public class ProductTemplateMessage : TemplateMessageBase<ProductElement>, IRichMessage
|
public class ProductTemplateMessage : TemplateMessageBase<ProductElement>, IRichMessage
|
||||||
{
|
{
|
||||||
|
[JsonPropertyName("template_type")]
|
||||||
public override string TemplateType => "product";
|
public override string TemplateType => "product";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template
|
namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template
|
||||||
{
|
{
|
||||||
public class TemplateMessageBase<T>
|
public class TemplateMessageBase<T> : RichMessageBase
|
||||||
{
|
{
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public string Text { get; set; }
|
public string Text { get; set; }
|
||||||
|
|
||||||
|
public override string Type => "template";
|
||||||
|
|
||||||
[JsonPropertyName("template_type")]
|
[JsonPropertyName("template_type")]
|
||||||
public virtual string TemplateType => string.Empty;
|
public virtual string TemplateType => string.Empty;
|
||||||
|
|
||||||
public T[] Elements { get; set; }
|
public T[] Elements { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
namespace BotSharp.Abstraction.Messaging.Models.RichContent;
|
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)
|
public TextMessage(string text)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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; }
|
||||||
|
}
|
||||||
|
|
@ -84,6 +84,9 @@ public partial class ConversationService : IConversationService
|
||||||
var hooks = _services.GetServices<IConversationHook>().ToList();
|
var hooks = _services.GetServices<IConversationHook>().ToList();
|
||||||
foreach (var hook in hooks)
|
foreach (var hook in hooks)
|
||||||
{
|
{
|
||||||
|
// If user connect agent first time
|
||||||
|
await hook.OnUserAgentConnectedInitially(sess);
|
||||||
|
|
||||||
await hook.OnConversationInitialized(record);
|
await hook.OnConversationInitialized(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,4 +118,15 @@ public partial class ConversationService : IConversationService
|
||||||
_state.Load(_conversationId);
|
_state.Load(_conversationId);
|
||||||
states.ForEach(x => _state.SetState(x.Split('=')[0], x.Split('=')[1]));
|
states.ForEach(x => _state.SetState(x.Split('=')[0], x.Split('=')[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task MarkConnectionReady(string conversationId)
|
||||||
|
{
|
||||||
|
var hooks = _services.GetServices<IConversationHook>();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,13 @@ public class ConversationController : ControllerBase, IApiAdapter
|
||||||
return ConversationViewModel.FromSession(conv);
|
return ConversationViewModel.FromSession(conv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPatch("/conversation/{conversationId}/ready")]
|
||||||
|
public async Task ReadyToInteractive([FromRoute] string conversationId)
|
||||||
|
{
|
||||||
|
var service = _services.GetRequiredService<IConversationService>();
|
||||||
|
await service.MarkConnectionReady(conversationId);
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet("/conversations/{agentId}")]
|
[HttpGet("/conversations/{agentId}")]
|
||||||
public async Task<IEnumerable<ConversationViewModel>> GetConversations()
|
public async Task<IEnumerable<ConversationViewModel>> GetConversations()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using BotSharp.Abstraction.Agents.Models;
|
using BotSharp.Abstraction.Agents.Models;
|
||||||
using BotSharp.Abstraction.Functions.Models;
|
using BotSharp.Abstraction.Functions.Models;
|
||||||
using BotSharp.Abstraction.Routing.Models;
|
using BotSharp.Abstraction.Routing.Models;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace BotSharp.OpenAPI.ViewModels.Agents;
|
namespace BotSharp.OpenAPI.ViewModels.Agents;
|
||||||
|
|
||||||
|
|
@ -15,12 +16,20 @@ public class AgentViewModel
|
||||||
public List<AgentResponse> Responses { get; set; }
|
public List<AgentResponse> Responses { get; set; }
|
||||||
public List<string> Samples { get; set; }
|
public List<string> Samples { get; set; }
|
||||||
public bool IsPublic { get; set; }
|
public bool IsPublic { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("allow_routing")]
|
||||||
public bool AllowRouting { get; set; }
|
public bool AllowRouting { get; set; }
|
||||||
public bool Disabled { get; set; }
|
public bool Disabled { get; set; }
|
||||||
public List<string> Profiles { get; set; }
|
public List<string> Profiles { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("routing_rules")]
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
public List<RoutingRule> RoutingRules { get; set; }
|
public List<RoutingRule> RoutingRules { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("created_datetime")]
|
||||||
public DateTime CreatedDateTime { get; set; }
|
public DateTime CreatedDateTime { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("updated_datetime")]
|
||||||
public DateTime UpdatedDateTime { get; set; }
|
public DateTime UpdatedDateTime { get; set; }
|
||||||
|
|
||||||
public static AgentViewModel FromAgent(Agent agent)
|
public static AgentViewModel FromAgent(Agent agent)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<LangVersion>$(LangVersion)</LangVersion>
|
<LangVersion>$(LangVersion)</LangVersion>
|
||||||
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
||||||
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
||||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
<GenerateDocumentationFile>$(GenerateDocumentationFile)</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<LangVersion>$(LangVersion)</LangVersion>
|
<LangVersion>$(LangVersion)</LangVersion>
|
||||||
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
||||||
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
||||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
<GenerateDocumentationFile>$(GenerateDocumentationFile)</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
using BotSharp.Abstraction.Messaging;
|
||||||
using Microsoft.AspNetCore.SignalR;
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
|
||||||
namespace BotSharp.Plugin.ChatHub.Hooks;
|
namespace BotSharp.Plugin.ChatHub.Hooks;
|
||||||
|
|
@ -14,6 +15,30 @@ public class ChatHubConversationHook : ConversationHookBase
|
||||||
_chatHub = chatHub;
|
_chatHub = chatHub;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override async Task OnUserAgentConnectedInitially(Conversation conversation)
|
||||||
|
{
|
||||||
|
var agentService = _services.GetService<IAgentService>();
|
||||||
|
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<RichMessageBase[]>(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)
|
public override async Task OnConversationInitialized(Conversation conversation)
|
||||||
{
|
{
|
||||||
var userService = _services.GetRequiredService<IUserService>();
|
var userService = _services.GetRequiredService<IUserService>();
|
||||||
|
|
|
||||||
|
|
@ -17,28 +17,6 @@ public class SignalRHub : Hub
|
||||||
_user = user;
|
_user = user;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task OnMessageReceivedFromClient(string message)
|
|
||||||
{
|
|
||||||
// await Clients.User(_user.Id).SendAsync("ReceiveMessage", message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Received message from client
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="user"></param>
|
|
||||||
/// <param name="message"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
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()
|
public override Task OnConnectedAsync()
|
||||||
{
|
{
|
||||||
Console.WriteLine($"SignalR Hub: {Context.UserIdentifier} connected in {Context.ConnectionId} [{DateTime.Now}]");
|
Console.WriteLine($"SignalR Hub: {Context.UserIdentifier} connected in {Context.ConnectionId} [{DateTime.Now}]");
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<LangVersion>$(LangVersion)</LangVersion>
|
<LangVersion>$(LangVersion)</LangVersion>
|
||||||
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
||||||
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
||||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
<GenerateDocumentationFile>$(GenerateDocumentationFile)</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<LangVersion>$(LangVersion)</LangVersion>
|
<LangVersion>$(LangVersion)</LangVersion>
|
||||||
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
||||||
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
||||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
<GenerateDocumentationFile>$(GenerateDocumentationFile)</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<LangVersion>$(LangVersion)</LangVersion>
|
<LangVersion>$(LangVersion)</LangVersion>
|
||||||
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
||||||
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
||||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
<GenerateDocumentationFile>$(GenerateDocumentationFile)</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<LangVersion>$(LangVersion)</LangVersion>
|
<LangVersion>$(LangVersion)</LangVersion>
|
||||||
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
||||||
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
||||||
<GenerateDocumentationFile>GenerateDocumentationFile</GenerateDocumentationFile>
|
<GenerateDocumentationFile>$(GenerateDocumentationFile)</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -10,4 +10,6 @@ public class AttachmentMessage : IRichMessage
|
||||||
|
|
||||||
[JsonPropertyName("attachment")]
|
[JsonPropertyName("attachment")]
|
||||||
public AttachmentBody Attachment { get; set; }
|
public AttachmentBody Attachment { get; set; }
|
||||||
|
|
||||||
|
public string Type => "template";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<LangVersion>$(LangVersion)</LangVersion>
|
<LangVersion>$(LangVersion)</LangVersion>
|
||||||
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
||||||
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
||||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
<GenerateDocumentationFile>$(GenerateDocumentationFile)</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<LangVersion>$(LangVersion)</LangVersion>
|
<LangVersion>$(LangVersion)</LangVersion>
|
||||||
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
||||||
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
||||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
<GenerateDocumentationFile>$(GenerateDocumentationFile)</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|
|
||||||
|
|
@ -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?"
|
||||||
|
}
|
||||||
|
]
|
||||||
4
src/web-live-chat/package-lock.json
generated
4
src/web-live-chat/package-lock.json
generated
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"name": "embedded-chat",
|
"name": "web-live-chat",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "embedded-chat",
|
"name": "web-live-chat",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@microsoft/signalr": "^8.0.0",
|
"@microsoft/signalr": "^8.0.0",
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,19 @@
|
||||||
* @property {string} assembly - The plugin assembly.
|
* @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
|
* @typedef {Object} ConversationModel
|
||||||
* @property {string} id - The conversation id.
|
* @property {string} id - The conversation id.
|
||||||
|
|
|
||||||
20
src/web-live-chat/src/lib/services/agent-service.js
Normal file
20
src/web-live-chat/src/lib/services/agent-service.js
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { agentListUrl, agentDetailUrl } from '$lib/services/api-endpoints.js';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Promise<import('$typedefs').AgentModel[]>}
|
||||||
|
*/
|
||||||
|
export async function getAgents() {
|
||||||
|
const response = await axios.get(agentListUrl);
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} id
|
||||||
|
* @returns {Promise<import('$typedefs').AgentModel>}
|
||||||
|
*/
|
||||||
|
export async function getAgent(id) {
|
||||||
|
let url = agentDetailUrl.replace("{id}", id);
|
||||||
|
const response = await axios.get(url);
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
|
@ -14,6 +14,7 @@ export const agentDetailUrl = `${host}/agent/{id}`;
|
||||||
|
|
||||||
// conversation
|
// conversation
|
||||||
export const conversationInitUrl = `${host}/conversation/{agentId}`
|
export const conversationInitUrl = `${host}/conversation/{agentId}`
|
||||||
|
export const conversationReadyUrl = `${host}/conversation/{conversationId}/ready`
|
||||||
export const conversationMessageUrl = `${host}/conversation/{agentId}/{conversationId}`
|
export const conversationMessageUrl = `${host}/conversation/{agentId}/{conversationId}`
|
||||||
export const conversationsUrl = `${host}/conversations/{agentId}`
|
export const conversationsUrl = `${host}/conversations/{agentId}`
|
||||||
export const dialogsUrl = `${host}/conversation/{conversationId}/dialogs`
|
export const dialogsUrl = `${host}/conversation/{conversationId}/dialogs`
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import {
|
||||||
conversationInitUrl,
|
conversationInitUrl,
|
||||||
conversationMessageUrl,
|
conversationMessageUrl,
|
||||||
dialogsUrl,
|
dialogsUrl,
|
||||||
|
conversationReadyUrl,
|
||||||
} from './api-endpoints.js';
|
} from './api-endpoints.js';
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
@ -17,6 +18,16 @@ export async function newConversation(agentId) {
|
||||||
return response.data;
|
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
|
* Get dialog history
|
||||||
* @param {string} conversationId
|
* @param {string} conversationId
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,8 @@
|
||||||
/** @type {import('$typedefs').ConversationModel} */
|
/** @type {import('$typedefs').ConversationModel} */
|
||||||
let conversation;
|
let conversation;
|
||||||
let conversationId = "undefined";
|
let conversationId = "undefined";
|
||||||
let agentId = "undefined";
|
|
||||||
|
let agentId = params.agentId;
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
let userToken = "";
|
let userToken = "";
|
||||||
|
|
@ -25,9 +26,11 @@
|
||||||
userToken = $page.url.searchParams.get('token') ?? "unauthorized";
|
userToken = $page.url.searchParams.get('token') ?? "unauthorized";
|
||||||
}
|
}
|
||||||
setAuthorization(userToken);
|
setAuthorization(userToken);
|
||||||
conversation = await newConversation(params.agentId);
|
|
||||||
|
// new conversation
|
||||||
|
conversation = await newConversation(agentId);
|
||||||
conversationId = conversation.id;
|
conversationId = conversation.id;
|
||||||
agentId = params.agentId;
|
|
||||||
window.location.href = `/chat/${agentId}/${conversationId}?token=${userToken}`;
|
window.location.href = `/chat/${agentId}/${conversationId}?token=${userToken}`;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,29 @@
|
||||||
<script>
|
<script>
|
||||||
import Chat from './chat-box.svelte'
|
import Chat from './chat-box.svelte';
|
||||||
|
import { page } from '$app/stores';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { setAuthorization } from '$lib/helpers/http';
|
||||||
|
import { myInfo } from '$lib/services/auth-service.js';
|
||||||
|
import { getAgent } from '$lib/services/agent-service.js';
|
||||||
|
|
||||||
|
const params = $page.params;
|
||||||
|
|
||||||
|
/** @type {import('$typedefs').AgentModel} */
|
||||||
|
let agent;
|
||||||
|
|
||||||
|
/** @type {import('$typedefs').UserModel} */
|
||||||
|
let currentUser;
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
const token = $page.url.searchParams.get('token') ?? "unauthorized";
|
||||||
|
setAuthorization(token);
|
||||||
|
|
||||||
|
currentUser = await myInfo(token);
|
||||||
|
|
||||||
|
// get agent profile
|
||||||
|
let agentId = params.agentId;
|
||||||
|
agent = await getAgent(agentId);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Chat />
|
<Chat currentUser={currentUser} agent={agent} />
|
||||||
|
|
@ -13,10 +13,9 @@
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import Link from 'svelte-link';
|
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 { 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 = {
|
const options = {
|
||||||
scrollbars: {
|
scrollbars: {
|
||||||
|
|
@ -32,9 +31,12 @@
|
||||||
const params = $page.params;
|
const params = $page.params;
|
||||||
|
|
||||||
let text = "Hi";
|
let text = "Hi";
|
||||||
|
|
||||||
|
/** @type {import('$typedefs').AgentModel} */
|
||||||
|
export let agent;
|
||||||
|
|
||||||
/** @type {import('$typedefs').UserModel} */
|
/** @type {import('$typedefs').UserModel} */
|
||||||
let currentUser;
|
export let currentUser;
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
let scrollbar;
|
let scrollbar;
|
||||||
|
|
@ -46,14 +48,15 @@
|
||||||
const token = $page.url.searchParams.get('token') ?? "unauthorized";
|
const token = $page.url.searchParams.get('token') ?? "unauthorized";
|
||||||
setAuthorization(token);
|
setAuthorization(token);
|
||||||
|
|
||||||
currentUser = await myInfo(token);
|
|
||||||
|
|
||||||
dialogs = await GetDialogs(params.conversationId);
|
dialogs = await GetDialogs(params.conversationId);
|
||||||
|
|
||||||
signalr.onMessageReceivedFromClient = onMessageReceivedFromClient;
|
signalr.onMessageReceivedFromClient = onMessageReceivedFromClient;
|
||||||
signalr.onMessageReceivedFromCsr = onMessageReceivedFromCsr;
|
signalr.onMessageReceivedFromCsr = onMessageReceivedFromCsr;
|
||||||
signalr.onMessageReceivedFromAssistant = onMessageReceivedFromAssistant;
|
signalr.onMessageReceivedFromAssistant = onMessageReceivedFromAssistant;
|
||||||
await signalr.start();
|
await signalr.start();
|
||||||
|
|
||||||
|
await conversationReady(params.conversationId);
|
||||||
|
|
||||||
const scrollElements = document.querySelectorAll('.scrollbar');
|
const scrollElements = document.querySelectorAll('.scrollbar');
|
||||||
scrollElements.forEach((item) => {
|
scrollElements.forEach((item) => {
|
||||||
scrollbar = OverlayScrollbars(item, options);
|
scrollbar = OverlayScrollbars(item, options);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue