2024-11-19 19:05:12 +00:00
using BotSharp.Abstraction.Files ;
using BotSharp.Abstraction.Options ;
2025-01-07 17:55:37 +00:00
using BotSharp.Abstraction.Routing ;
2024-11-19 19:05:12 +00:00
using BotSharp.Core.Infrastructures ;
using BotSharp.Plugin.Twilio.Interfaces ;
using BotSharp.Plugin.Twilio.Models ;
using BotSharp.Plugin.Twilio.OutboundPhoneCallHandler.LlmContexts ;
using Twilio.Rest.Api.V2010.Account ;
using Twilio.Types ;
namespace BotSharp.Plugin.Twilio.OutboundPhoneCallHandler.Functions
{
public class HandleOutboundPhoneCallFn : IFunctionCallback
{
private readonly IServiceProvider _services ;
private readonly ILogger < HandleOutboundPhoneCallFn > _logger ;
private readonly BotSharpOptions _options ;
private readonly TwilioSetting _twilioSetting ;
2024-12-04 22:12:02 +00:00
public string Name = > "util-twilio-twilio_outbound_phone_call" ;
2024-11-19 19:05:12 +00:00
public string Indication = > "Dialing the number" ;
public HandleOutboundPhoneCallFn (
IServiceProvider services ,
ILogger < HandleOutboundPhoneCallFn > logger ,
BotSharpOptions options ,
TwilioSetting twilioSetting )
{
_services = services ;
_logger = logger ;
_options = options ;
_twilioSetting = twilioSetting ;
}
public async Task < bool > Execute ( RoleDialogModel message )
{
var args = JsonSerializer . Deserialize < LlmContextIn > ( message . FunctionArgs , _options . JsonSerializerOptions ) ;
if ( args . PhoneNumber . Length ! = 12 | | ! args . PhoneNumber . StartsWith ( "+1" , StringComparison . OrdinalIgnoreCase ) )
{
2024-11-20 04:48:31 +00:00
var error = $"Invalid phone number format: {args.PhoneNumber}" ;
_logger . LogError ( error ) ;
message . Content = error ;
2024-11-19 19:05:12 +00:00
return false ;
}
2024-11-20 04:48:31 +00:00
2024-11-19 19:05:12 +00:00
if ( string . IsNullOrWhiteSpace ( args . InitialMessage ) )
{
_logger . LogError ( "Initial message is empty." ) ;
2024-11-20 04:48:31 +00:00
message . Content = "There is an error when generating phone message." ;
2024-11-19 19:05:12 +00:00
return false ;
}
2024-11-20 04:48:31 +00:00
2025-01-07 17:55:37 +00:00
var convService = _services . GetRequiredService < IConversationService > ( ) ;
var convStorage = _services . GetRequiredService < IConversationStorage > ( ) ;
var routing = _services . GetRequiredService < IRoutingContext > ( ) ;
2024-11-19 19:05:12 +00:00
var fileStorage = _services . GetRequiredService < IFileStorageService > ( ) ;
2024-11-20 04:48:31 +00:00
var sessionManager = _services . GetRequiredService < ITwilioSessionManager > ( ) ;
2025-01-07 17:55:37 +00:00
// Fork conversation
var entryAgentId = routing . EntryAgentId ;
var newConv = await convService . NewConversation ( new Abstraction . Conversations . Models . Conversation
{
AgentId = entryAgentId ,
Channel = ConversationChannel . Phone
} ) ;
var conversationId = newConv . Id ;
convStorage . Append ( conversationId , new RoleDialogModel ( AgentRole . User , "Hi, I'm calling to check my work order quote status, please help me locate my work order number and let me know what to do next." )
{
CurrentAgentId = entryAgentId
} ) ;
convStorage . Append ( conversationId , new RoleDialogModel ( AgentRole . Assistant , args . InitialMessage )
{
CurrentAgentId = entryAgentId
} ) ;
2024-11-20 04:48:31 +00:00
// Generate audio
var completion = CompletionProvider . GetAudioCompletion ( _services , "openai" , "tts-1" ) ;
2024-11-19 19:05:12 +00:00
var data = await completion . GenerateAudioFromTextAsync ( args . InitialMessage ) ;
var fileName = $"intial.mp3" ;
fileStorage . SaveSpeechFile ( conversationId , fileName , data ) ;
2024-11-20 04:48:31 +00:00
// Call phone number
2024-11-19 19:05:12 +00:00
await sessionManager . SetAssistantReplyAsync ( conversationId , 0 , new AssistantMessage
{
Content = args . InitialMessage ,
SpeechFileName = fileName
} ) ;
2024-11-20 04:48:31 +00:00
2024-11-19 19:05:12 +00:00
var call = await CallResource . CreateAsync (
url : new Uri ( $"{_twilioSetting.CallbackHost}/twilio/voice/init-call?conversationId={conversationId}" ) ,
to : new PhoneNumber ( args . PhoneNumber ) ,
from : new PhoneNumber ( _twilioSetting . PhoneNumber ) ) ;
2024-11-20 04:48:31 +00:00
2025-01-07 17:55:37 +00:00
message . Content = $"The generated phone message: {args.InitialMessage}. \r\n[Conversation ID: {conversationId}]" ? ? message . Content ;
2024-11-19 19:05:12 +00:00
message . StopCompletion = true ;
return true ;
}
}
}