Skip to content

Commit b0432e1

Browse files
authored
Merge pull request #955 from hchen2020/master
util-twilio-leave_voicemail
2 parents 24657bd + 58a0500 commit b0432e1

File tree

10 files changed

+116
-32
lines changed

10 files changed

+116
-32
lines changed

src/Plugins/BotSharp.Plugin.Twilio/BotSharp.Plugin.Twilio.csproj

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@
1414
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\util-twilio-hangup_phone_call.json" />
1515
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\util-twilio-text_message.json" />
1616
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\util-twilio-outbound_phone_call.json" />
17-
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\util-twilio-hangup_phone_call.fn.liquid" />
18-
<None Remove="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\util-twilio-outbound_phone_call.fn.liquid" />
1917
</ItemGroup>
2018

2119
<ItemGroup>
20+
<Content Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\util-twilio-leave_voicemail.json">
21+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
22+
</Content>
2223
<Content Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\util-twilio-transfer_phone_call.json">
2324
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
2425
</Content>
@@ -31,12 +32,6 @@
3132
<Content Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\functions\util-twilio-outbound_phone_call.json">
3233
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
3334
</Content>
34-
<Content Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\util-twilio-hangup_phone_call.fn.liquid">
35-
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
36-
</Content>
37-
<Content Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\util-twilio-outbound_phone_call.fn.liquid">
38-
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
39-
</Content>
4035
</ItemGroup>
4136

4237
<ItemGroup>
@@ -51,8 +46,4 @@
5146
<ProjectReference Include="..\..\Infrastructure\BotSharp.Core\BotSharp.Core.csproj" />
5247
</ItemGroup>
5348

54-
<ItemGroup>
55-
<Folder Include="data\agents\6745151e-6d46-4a02-8de4-1c4f21c7da95\templates\" />
56-
</ItemGroup>
57-
5849
</Project>

src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioStreamController.cs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,6 @@ public async Task<TwiMLResult> InitiateStreamConversation(ConversationalVoiceReq
3838
var twilio = _services.GetRequiredService<TwilioService>();
3939
VoiceResponse response = default!;
4040

41-
if (request.AnsweredBy == "machine_start" &&
42-
request.Direction == "outbound-api" &&
43-
request.InitAudioFile != null)
44-
{
45-
response = new VoiceResponse();
46-
var url = twilio.GetSpeechPath(request.ConversationId, request.InitAudioFile);
47-
response.Play(new Uri(url));
48-
return TwiML(response);
49-
}
50-
5141
var instruction = new ConversationalVoiceResponse
5242
{
5343
ConversationId = request.ConversationId,
@@ -70,7 +60,24 @@ await HookEmitter.Emit<ITwilioSessionHook>(_services, async hook =>
7060

7161
request.ConversationId = await InitConversation(request);
7262
instruction.ConversationId = request.ConversationId;
73-
response = twilio.ReturnBidirectionalMediaStreamsInstructions(instruction);
63+
64+
if (request.AnsweredBy == "machine_start" &&
65+
request.Direction == "outbound-api")
66+
{
67+
response = new VoiceResponse();
68+
69+
await HookEmitter.Emit<ITwilioCallStatusHook>(_services, async hook =>
70+
{
71+
await hook.OnVoicemailStarting(request);
72+
});
73+
74+
var url = twilio.GetSpeechPath(request.ConversationId, "voicemail.mp3");
75+
response.Play(new Uri(url));
76+
}
77+
else
78+
{
79+
response = twilio.ReturnBidirectionalMediaStreamsInstructions(instruction);
80+
}
7481

7582
await HookEmitter.Emit<ITwilioSessionHook>(_services, async hook =>
7683
{

src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioVoiceController.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -475,8 +475,7 @@ public async Task<ActionResult> PhoneCallStatus(ConversationalVoiceRequest reque
475475
if (request.CallStatus == "completed")
476476
{
477477
if (request.AnsweredBy == "machine_start" &&
478-
request.Direction == "outbound-api" &&
479-
request.InitAudioFile != null)
478+
request.Direction == "outbound-api")
480479
{
481480
// voicemail
482481
await HookEmitter.Emit<ITwilioCallStatusHook>(_services, async hook =>

src/Plugins/BotSharp.Plugin.Twilio/Interfaces/ITwilioCallStatusHook.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ public interface ITwilioCallStatusHook
88
Task OnVoicemailLeft(ConversationalVoiceRequest request);
99
Task OnUserDisconnected(ConversationalVoiceRequest request);
1010
Task OnRecordingCompleted(ConversationalVoiceRequest request);
11+
Task OnVoicemailStarting(ConversationalVoiceRequest request);
1112
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using BotSharp.Abstraction.Files;
2+
using BotSharp.Abstraction.Routing;
3+
using BotSharp.Core.Infrastructures;
4+
using BotSharp.Plugin.Twilio.OutboundPhoneCallHandler.LlmContexts;
5+
6+
namespace BotSharp.Plugin.Twilio.OutboundPhoneCallHandler.Functions;
7+
8+
public class LeaveVoicemailFn : IFunctionCallback
9+
{
10+
private readonly IServiceProvider _services;
11+
private readonly ILogger _logger;
12+
private readonly TwilioSetting _setting;
13+
14+
public string Name => "util-twilio-leave_voicemail";
15+
public string Indication => "leaving a voicemail";
16+
17+
public LeaveVoicemailFn(
18+
IServiceProvider services,
19+
ILogger<LeaveVoicemailFn> logger,
20+
TwilioSetting setting)
21+
{
22+
_services = services;
23+
_logger = logger;
24+
_setting = setting;
25+
}
26+
27+
public async Task<bool> Execute(RoleDialogModel message)
28+
{
29+
var args = JsonSerializer.Deserialize<LeaveVoicemailArgs>(message.FunctionArgs);
30+
31+
var fileStorage = _services.GetRequiredService<IFileStorageService>();
32+
var routing = _services.GetRequiredService<IRoutingService>();
33+
var conversationId = routing.Context.ConversationId;
34+
var states = _services.GetRequiredService<IConversationStateService>();
35+
var callSid = states.GetState("twilio_call_sid");
36+
37+
if (string.IsNullOrEmpty(callSid))
38+
{
39+
message.Content = "The call has not been initiated.";
40+
_logger.LogError(message.Content);
41+
return false;
42+
}
43+
44+
// Generate voice message audio
45+
string initAudioFile = null;
46+
if (!string.IsNullOrEmpty(args.VoicemailMessage))
47+
{
48+
var completion = CompletionProvider.GetAudioCompletion(_services, "openai", "tts-1");
49+
var data = await completion.GenerateAudioFromTextAsync(args.VoicemailMessage);
50+
initAudioFile = "voicemail.mp3";
51+
fileStorage.SaveSpeechFile(conversationId, initAudioFile, data);
52+
}
53+
54+
message.Content = args.VoicemailMessage;
55+
message.StopCompletion = true;
56+
57+
return true;
58+
}
59+
}

src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Hooks/OutboundPhoneCallHandlerUtilityHook.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public class OutboundPhoneCallHandlerUtilityHook : IAgentUtilityHook
1010
private static string TRANSFER_PHONE_CALL_FN = $"{PREFIX}transfer_phone_call";
1111
private static string HANGUP_PHONE_CALL_FN = $"{PREFIX}hangup_phone_call";
1212
private static string TEXT_MESSAGE_FN = $"{PREFIX}text_message";
13+
private static string LEAVE_VOICEMAIL_FN = $"{PREFIX}leave_voicemail";
1314

1415
public void AddUtilities(List<AgentUtility> utilities)
1516
{
@@ -21,12 +22,11 @@ public void AddUtilities(List<AgentUtility> utilities)
2122
new($"{OUTBOUND_PHONE_CALL_FN}"),
2223
new($"{TRANSFER_PHONE_CALL_FN}"),
2324
new($"{HANGUP_PHONE_CALL_FN}"),
24-
new($"{TEXT_MESSAGE_FN}")
25+
new($"{TEXT_MESSAGE_FN}"),
26+
new($"{LEAVE_VOICEMAIL_FN}")
2527
],
2628
Templates =
2729
[
28-
new($"{OUTBOUND_PHONE_CALL_FN}.fn"),
29-
new($"{HANGUP_PHONE_CALL_FN}.fn")
3030
]
3131
};
3232

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace BotSharp.Plugin.Twilio.OutboundPhoneCallHandler.LlmContexts;
4+
5+
public class LeaveVoicemailArgs
6+
{
7+
[JsonPropertyName("phone_number")]
8+
public string PhoneNumber { get; set; } = null!;
9+
10+
[JsonPropertyName("voicemail_message")]
11+
public string VoicemailMessage { get; set; } = null!;
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "util-twilio-leave_voicemail",
3+
"description": "If the user wants you to leave a voicemail.",
4+
"visibility_expression": "{% if states.channel == 'phone' %}visible{% endif %}",
5+
"parameters": {
6+
"type": "object",
7+
"properties": {
8+
"voicemail_message": {
9+
"type": "string",
10+
"description": "User voicemail with details."
11+
},
12+
"phone_number": {
13+
"type": "string",
14+
"description": "Phone number to callback."
15+
}
16+
},
17+
"required": [ "voicemail_message", "phone_number" ]
18+
}
19+
}

src/Plugins/BotSharp.Plugin.Twilio/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/util-twilio-hangup_phone_call.fn.liquid

Lines changed: 0 additions & 3 deletions
This file was deleted.

src/Plugins/BotSharp.Plugin.Twilio/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/util-twilio-outbound_phone_call.fn.liquid

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)