Merge pull request #536 from visagang/features/vguruparan
Add new email handler utility
This commit is contained in:
commit
c27acab711
|
|
@ -0,0 +1,11 @@
|
|||
namespace BotSharp.Abstraction.Email.Settings;
|
||||
|
||||
public class EmailHandlerSettings
|
||||
{
|
||||
public string EmailAddress { get; set; } = string.Empty;
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Username { get; set; } = string.Empty;
|
||||
public string Password { get; set; } = string.Empty;
|
||||
public string SMTPServer { get; set; } = string.Empty;
|
||||
public int SMTPPort { get; set; }
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(TargetFramework)</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>$(LangVersion)</LangVersion>
|
||||
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
||||
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
||||
<GenerateDocumentationFile>$(GenerateDocumentationFile)</GenerateDocumentationFile>
|
||||
<OutputPath>$(SolutionDir)packages</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\handle_email_request.json" />
|
||||
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\handle_email_request.fn.liquid" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\handle_email_request.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\handle_email_request.fn.liquid">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MailKit" Version="4.7.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Infrastructure\BotSharp.Core\BotSharp.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
using BotSharp.Abstraction.Agents;
|
||||
using BotSharp.Abstraction.Email.Settings;
|
||||
using BotSharp.Abstraction.Settings;
|
||||
using BotSharp.Plugin.EmailHandler.Hooks;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BotSharp.Plugin.EmailHandler
|
||||
{
|
||||
public class EmailHandlerPlugin : IBotSharpPlugin
|
||||
{
|
||||
public string Id => "a8e217de-e413-47a8-bbf1-af9207392a63";
|
||||
public string Name => "Email Handler";
|
||||
public string Description => "Empower agent to handle sending out emails";
|
||||
public string IconUrl => "https://cdn-icons-png.freepik.com/512/6711/6711567.png";
|
||||
|
||||
public void RegisterDI(IServiceCollection services, IConfiguration config)
|
||||
{
|
||||
services.AddScoped(provider =>
|
||||
{
|
||||
var settingService = provider.GetRequiredService<ISettingService>();
|
||||
return settingService.Bind<EmailHandlerSettings>("EmailHandler");
|
||||
});
|
||||
|
||||
services.AddScoped<IAgentHook, EmailHandlerHook>();
|
||||
services.AddScoped<IAgentUtilityHook, EmailHandlerUtilityHook>();
|
||||
}
|
||||
}
|
||||
}
|
||||
13
src/Plugins/BotSharp.Plugin.EmailHandler/Enums/Utility.cs
Normal file
13
src/Plugins/BotSharp.Plugin.EmailHandler/Enums/Utility.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BotSharp.Plugin.EmailHandler.Enums
|
||||
{
|
||||
public class Utility
|
||||
{
|
||||
public const string EmailHandler = "email-handler";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
using BotSharp.Abstraction.Email.Settings;
|
||||
using BotSharp.Plugin.EmailHandler.LlmContexts;
|
||||
using MailKit;
|
||||
using MailKit.Net.Smtp;
|
||||
using MailKit.Security;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MimeKit;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace BotSharp.Plugin.EmailHandler.Functions;
|
||||
|
||||
public class HandleEmailRequestFn : IFunctionCallback
|
||||
{
|
||||
public string Name => "handle_email_request";
|
||||
public string Indication => "Handling email request";
|
||||
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly ILogger<HandleEmailRequestFn> _logger;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly IHttpContextAccessor _context;
|
||||
private readonly BotSharpOptions _options;
|
||||
private readonly EmailHandlerSettings _emailSettings;
|
||||
|
||||
public HandleEmailRequestFn(IServiceProvider services,
|
||||
ILogger<HandleEmailRequestFn> logger,
|
||||
IHttpClientFactory httpClientFactory,
|
||||
IHttpContextAccessor context,
|
||||
BotSharpOptions options,
|
||||
EmailHandlerSettings emailPluginSettings)
|
||||
{
|
||||
_services = services;
|
||||
_logger = logger;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_context = context;
|
||||
_options = options;
|
||||
_emailSettings = emailPluginSettings;
|
||||
}
|
||||
public async Task<bool> Execute(RoleDialogModel message)
|
||||
{
|
||||
var args = JsonSerializer.Deserialize<LlmContextIn>(message.FunctionArgs, _options.JsonSerializerOptions);
|
||||
var recipient = args?.ToAddress;
|
||||
var body = args?.Content;
|
||||
var subject = args?.Subject;
|
||||
|
||||
try
|
||||
{
|
||||
var mailMessage = new MimeMessage();
|
||||
mailMessage.From.Add(new MailboxAddress(_emailSettings.Name, _emailSettings.EmailAddress));
|
||||
mailMessage.To.Add(new MailboxAddress("", recipient));
|
||||
mailMessage.Subject = subject;
|
||||
mailMessage.Body = new TextPart("plain")
|
||||
{
|
||||
Text = body
|
||||
};
|
||||
var response = await HandleSendEmailBySMTP(mailMessage);
|
||||
_logger.LogWarning($"Email successfully send over to {recipient}. Email Subject: {subject} [{response}]");
|
||||
message.Content = response;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = $"Failed to send the email. {ex.Message}";
|
||||
_logger.LogError($"{msg}\n(Error: {ex.Message})");
|
||||
message.Content = msg;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> HandleSendEmailBySMTP(MimeMessage mailMessage)
|
||||
{
|
||||
using var smtpClient = new SmtpClient();
|
||||
await smtpClient.ConnectAsync(_emailSettings.SMTPServer, _emailSettings.SMTPPort, SecureSocketOptions.StartTls);
|
||||
await smtpClient.AuthenticateAsync(_emailSettings.EmailAddress, _emailSettings.Password);
|
||||
var response = await smtpClient.SendAsync(mailMessage);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
using BotSharp.Abstraction.Agents;
|
||||
using BotSharp.Abstraction.Agents.Enums;
|
||||
using BotSharp.Abstraction.Agents.Settings;
|
||||
using BotSharp.Abstraction.Functions.Models;
|
||||
using BotSharp.Abstraction.Repositories;
|
||||
using BotSharp.Plugin.EmailHandler.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BotSharp.Plugin.EmailHandler.Hooks;
|
||||
|
||||
public class EmailHandlerHook : AgentHookBase
|
||||
{
|
||||
private static string FUNCTION_NAME = "handle_email_request";
|
||||
|
||||
public override string SelfId => string.Empty;
|
||||
|
||||
public EmailHandlerHook(IServiceProvider services, AgentSettings settings)
|
||||
: base(services, settings)
|
||||
{
|
||||
}
|
||||
public override void OnAgentLoaded(Agent agent)
|
||||
{
|
||||
var conv = _services.GetRequiredService<IConversationService>();
|
||||
var isConvMode = conv.IsConversationMode();
|
||||
var isEnabled = !agent.Utilities.IsNullOrEmpty() && agent.Utilities.Contains(Utility.EmailHandler);
|
||||
|
||||
if (isConvMode && isEnabled)
|
||||
{
|
||||
var (prompt, fn) = GetPromptAndFunction();
|
||||
if (fn != null)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(prompt))
|
||||
{
|
||||
agent.Instruction += $"\r\n\r\n{prompt}\r\n\r\n";
|
||||
}
|
||||
|
||||
if (agent.Functions == null)
|
||||
{
|
||||
agent.Functions = new List<FunctionDef> { fn };
|
||||
}
|
||||
else
|
||||
{
|
||||
agent.Functions.Add(fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.OnAgentLoaded(agent);
|
||||
}
|
||||
|
||||
private (string, FunctionDef?) GetPromptAndFunction()
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var agent = db.GetAgent(BuiltInAgentId.UtilityAssistant);
|
||||
var prompt = agent?.Templates?.FirstOrDefault(x => x.Name.IsEqualTo($"{FUNCTION_NAME}.fn"))?.Content ?? string.Empty;
|
||||
var loadAttachmentFn = agent?.Functions?.FirstOrDefault(x => x.Name.IsEqualTo(FUNCTION_NAME));
|
||||
return (prompt, loadAttachmentFn);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
using BotSharp.Abstraction.Agents;
|
||||
using BotSharp.Plugin.EmailHandler.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BotSharp.Plugin.EmailHandler.Hooks
|
||||
{
|
||||
public class EmailHandlerUtilityHook : IAgentUtilityHook
|
||||
{
|
||||
public void AddUtilities(List<string> utilities)
|
||||
{
|
||||
utilities.Add(Utility.EmailHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BotSharp.Plugin.EmailHandler.LlmContexts
|
||||
{
|
||||
public class LlmContextIn
|
||||
{
|
||||
[JsonPropertyName("to_address")]
|
||||
public string? ToAddress { get; set; }
|
||||
|
||||
[JsonPropertyName("email_content")]
|
||||
public string? Content { get; set; }
|
||||
[JsonPropertyName("subject")]
|
||||
public string? Subject { get; set; }
|
||||
}
|
||||
}
|
||||
19
src/Plugins/BotSharp.Plugin.EmailHandler/Using.cs
Normal file
19
src/Plugins/BotSharp.Plugin.EmailHandler/Using.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
global using System;
|
||||
global using System.Collections.Generic;
|
||||
global using System.Text;
|
||||
global using BotSharp.Abstraction.Conversations;
|
||||
global using BotSharp.Abstraction.Plugins;
|
||||
global using System.Text.Json;
|
||||
global using BotSharp.Abstraction.Conversations.Models;
|
||||
global using System.Threading.Tasks;
|
||||
global using BotSharp.Abstraction.Functions;
|
||||
global using BotSharp.Abstraction.Agents.Models;
|
||||
global using BotSharp.Abstraction.Templating;
|
||||
global using Microsoft.Extensions.DependencyInjection;
|
||||
global using System.Linq;
|
||||
global using BotSharp.Abstraction.Utilities;
|
||||
global using BotSharp.Abstraction.Messaging;
|
||||
global using BotSharp.Abstraction.Messaging.Models.RichContent;
|
||||
global using BotSharp.Abstraction.Options;
|
||||
global using BotSharp.Abstraction.Http.Settings;
|
||||
global using BotSharp.Abstraction.Messaging.Enums;
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "handle_email_request",
|
||||
"description": "If the user requests to send an email, you need to capture the email content and the recipient email address. If the user explicitly enter email subject use the same if not intelligently capture the email subject from the content. Then call this function to send out email.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"to_address": {
|
||||
"type": "string",
|
||||
"description": "The email address to which the email should be sent to. It needs to be a valid email address in the correct string format."
|
||||
},
|
||||
"email_content": {
|
||||
"type": "string",
|
||||
"description": "The content of the email which needs to be send over. It can be plain string or a raw html."
|
||||
},
|
||||
"subject": {
|
||||
"type": "string",
|
||||
"description": "The subject of the email which needs to be send over."
|
||||
}
|
||||
},
|
||||
"required": [ "to_address", "email_content", "subject" ]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
Please call handle_email_request if user wants to send out an email.
|
||||
Loading…
Reference in a new issue