From f457c83b6b68c4a26c887ee1f62a1022ef0b6691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=93=E7=A3=8A?= Date: Tue, 29 Apr 2025 09:41:58 +0800 Subject: [PATCH 01/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 38b1e023..adb0f064 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ BotSharp uses component design, the kernel is kept to a minimum, and business fu - [ ] A2A - [x] MCP -- [ ] Realtime +- [x] Realtime - [ ] Computer Use - [x] Browser Use - [x] Database Assistant From 18a27bf437153a021b57ecd88772465af3658277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=93=E7=A3=8A?= Date: Tue, 29 Apr 2025 10:21:55 +0800 Subject: [PATCH 02/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index adb0f064..e8284e51 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ BotSharp uses component design, the kernel is kept to a minimum, and business fu - [ ] A2A - [x] MCP -- [x] Realtime +- [x] Realtime - [ ] Computer Use - [x] Browser Use - [x] Database Assistant From 42d9f5cc0728948ecf0ca6cf17bbfb75da888fd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=93=E7=A3=8A?= Date: Tue, 29 Apr 2025 10:29:38 +0800 Subject: [PATCH 03/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e8284e51..adb0f064 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ BotSharp uses component design, the kernel is kept to a minimum, and business fu - [ ] A2A - [x] MCP -- [x] Realtime +- [x] Realtime - [ ] Computer Use - [x] Browser Use - [x] Database Assistant From 094fea58a4ef7cb0547775f17076405efaeab495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=93=E7=A3=8A?= Date: Tue, 29 Apr 2025 10:35:07 +0800 Subject: [PATCH 04/14] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index adb0f064..89fcc0e8 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,6 @@ BotSharp uses component design, the kernel is kept to a minimum, and business fu - BotSharp.Plugin.ChatbotUI ### Roadmap - - [ ] A2A - [x] MCP - [x] Realtime From fd2b5d1b016b2e515f8109e4545caad333ff8f25 Mon Sep 17 00:00:00 2001 From: "nick.yi" Date: Tue, 29 Apr 2025 11:28:56 +0800 Subject: [PATCH 05/14] optimize ITwilioCallStatusHook --- .../Controllers/TwilioVoiceController.cs | 42 +++++++++++++------ .../Interfaces/ITwilioCallStatusHook.cs | 17 ++++---- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioVoiceController.cs b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioVoiceController.cs index 0ff8b90c..b5bbb6bc 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioVoiceController.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioVoiceController.cs @@ -346,35 +346,53 @@ public class TwilioVoiceController : TwilioController if (twilio.MachineDetected(request)) { // voicemail - await HookEmitter.Emit(_services, - async hook => await hook.OnVoicemailLeft(request)); + await HookEmitter.Emit(_services, + async hook => + { + if (hook.IsMatch(request)) await hook.OnVoicemailLeft(request); + }); } else { // phone call completed - await HookEmitter.Emit(_services, - async x => await x.OnUserDisconnected(request)); + await HookEmitter.Emit(_services, + async hook => + { + if (hook.IsMatch(request)) await hook.OnUserDisconnected(request); + }); } } else if (request.CallStatus == "busy") { - await HookEmitter.Emit(_services, - async x => await x.OnCallBusyStatus(request)); + await HookEmitter.Emit(_services, + async hook => + { + if (hook.IsMatch(request)) await hook.OnCallBusyStatus(request); + }); } else if (request.CallStatus == "no-answer") { - await HookEmitter.Emit(_services, - async x => await x.OnCallNoAnswerStatus(request)); + await HookEmitter.Emit(_services, + async hook => + { + if (hook.IsMatch(request)) await hook.OnCallNoAnswerStatus(request); + }); } else if (request.CallStatus == "canceled") { - await HookEmitter.Emit(_services, - async x => await x.OnCallCanceledStatus(request)); + await HookEmitter.Emit(_services, + async hook => + { + if (hook.IsMatch(request)) await hook.OnCallCanceledStatus(request); + }); } else if (request.CallStatus == "failed") { - await HookEmitter.Emit(_services, - async x => await x.OnCallFailedStatus(request)); + await HookEmitter.Emit(_services, + async hook => + { + if (hook.IsMatch(request)) await hook.OnCallFailedStatus(request); + }); } return Ok(); diff --git a/src/Plugins/BotSharp.Plugin.Twilio/Interfaces/ITwilioCallStatusHook.cs b/src/Plugins/BotSharp.Plugin.Twilio/Interfaces/ITwilioCallStatusHook.cs index e04d3ae7..ae461595 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/Interfaces/ITwilioCallStatusHook.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/Interfaces/ITwilioCallStatusHook.cs @@ -5,10 +5,11 @@ namespace BotSharp.Plugin.Twilio.Interfaces; public interface ITwilioCallStatusHook { - Task OnVoicemailLeft(ConversationalVoiceRequest request); - Task OnUserDisconnected(ConversationalVoiceRequest request); - Task OnRecordingCompleted(ConversationalVoiceRequest request); - Task OnVoicemailStarting(ConversationalVoiceRequest request); + bool IsMatch(ConversationalVoiceRequest request) => true; + Task OnVoicemailLeft(ConversationalVoiceRequest request) => Task.CompletedTask; + Task OnUserDisconnected(ConversationalVoiceRequest request) => Task.CompletedTask; + Task OnRecordingCompleted(ConversationalVoiceRequest request) => Task.CompletedTask; + Task OnVoicemailStarting(ConversationalVoiceRequest request)=> Task.CompletedTask; /// /// 1. The recipient's phone line is already engaged. @@ -17,11 +18,11 @@ public interface ITwilioCallStatusHook /// /// /// - Task OnCallBusyStatus(ConversationalVoiceRequest request); + Task OnCallBusyStatus(ConversationalVoiceRequest request)=> Task.CompletedTask; - Task OnCallNoAnswerStatus(ConversationalVoiceRequest request); + Task OnCallNoAnswerStatus(ConversationalVoiceRequest request) => Task.CompletedTask; - Task OnCallCanceledStatus(ConversationalVoiceRequest request); + Task OnCallCanceledStatus(ConversationalVoiceRequest request)=> Task.CompletedTask; - Task OnCallFailedStatus(ConversationalVoiceRequest request); + Task OnCallFailedStatus(ConversationalVoiceRequest request)=> Task.CompletedTask; } From 34658d4468b6fb045a760ca309dc2b124ef94969 Mon Sep 17 00:00:00 2001 From: "nick.yi" Date: Tue, 29 Apr 2025 13:35:48 +0800 Subject: [PATCH 06/14] GetConversations() add channelId query condition --- .../Repositories/Filters/ConversationFilter.cs | 1 + .../Repository/FileRepository/FileRepository.Conversation.cs | 4 ++++ .../Repository/MongoRepository.Conversation.cs | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/ConversationFilter.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/ConversationFilter.cs index e5eed361..9ba98c5d 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/ConversationFilter.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/ConversationFilter.cs @@ -12,6 +12,7 @@ public class ConversationFilter public string? AgentId { get; set; } public string? Status { get; set; } public string? Channel { get; set; } + public string? ChannelId { get; set; } public string? UserId { get; set; } public DateTime? StartTime { get; set; } diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Conversation.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Conversation.cs index b8ff420e..3b60a61a 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Conversation.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Conversation.cs @@ -430,6 +430,10 @@ public partial class FileRepository { matched = matched && record.Channel == filter.Channel; } + if(filter?.ChannelId != null) + { + matched = matched && record.ChannelId == filter.ChannelId; + } if (filter?.UserId != null) { matched = matched && record.UserId == filter.UserId; diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs index f0e89473..722c7730 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs @@ -371,6 +371,10 @@ public partial class MongoRepository { convFilters.Add(convBuilder.Eq(x => x.Channel, filter.Channel)); } + if (!string.IsNullOrEmpty(filter?.ChannelId)) + { + convFilters.Add(convBuilder.Eq(x => x.ChannelId, filter.ChannelId)); + } if (!string.IsNullOrEmpty(filter?.UserId)) { convFilters.Add(convBuilder.Eq(x => x.UserId, filter.UserId)); From 2d42673d683ac02b36e217feacb9e4c1e4a3bfc0 Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Tue, 29 Apr 2025 11:53:40 -0500 Subject: [PATCH 07/14] Adding inbound call recording. --- .../Controllers/TwilioInboundController.cs | 6 ++++++ .../Controllers/TwilioRecordController.cs | 4 ++++ .../Controllers/TwilioVoiceController.cs | 18 +++++++++++------- .../Services/TwilioService.cs | 18 ++++++++++++++++++ 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioInboundController.cs b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioInboundController.cs index e82908a0..095f3d25 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioInboundController.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioInboundController.cs @@ -107,6 +107,12 @@ public class TwilioInboundController : TwilioController response.Redirect(new Uri($"{_settings.CallbackHost}/twilio/voice/reply/{seqNum}?agent-id={request.AgentId}&conversation-id={request.ConversationId}&{twilio.GenerateStatesParameter(request.States)}"), HttpMethod.Post); } } + + _ = Task.Run(async () => + { + await Task.Delay(1500); + await twilio.StartRecording(request.CallSid, request.AgentId, request.ConversationId); + }); } await HookEmitter.Emit(_services, async hook => diff --git a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioRecordController.cs b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioRecordController.cs index 65b2a5ad..4e4b1c75 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioRecordController.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioRecordController.cs @@ -38,6 +38,10 @@ public class TwilioRecordController : TwilioController // recording completed await HookEmitter.Emit(_services, x => x.OnRecordingCompleted(request)); } + else + { + _logger.LogError($"Unknown record status: {request.CallStatus}, {request.CallSid}"); + } return Ok(); } diff --git a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioVoiceController.cs b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioVoiceController.cs index b5bbb6bc..42582f70 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioVoiceController.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioVoiceController.cs @@ -214,7 +214,7 @@ public class TwilioVoiceController : TwilioController var reply = await sessionManager.GetAssistantReplyAsync(request.ConversationId, request.SeqNum); VoiceResponse response; - + if (request.AIResponseWaitTime > 10) { // Wait AI Response Timeout @@ -381,19 +381,23 @@ public class TwilioVoiceController : TwilioController else if (request.CallStatus == "canceled") { await HookEmitter.Emit(_services, - async hook => - { - if (hook.IsMatch(request)) await hook.OnCallCanceledStatus(request); + async hook => + { + if (hook.IsMatch(request)) await hook.OnCallCanceledStatus(request); }); } else if (request.CallStatus == "failed") { await HookEmitter.Emit(_services, - async hook => - { - if (hook.IsMatch(request)) await hook.OnCallFailedStatus(request); + async hook => + { + if (hook.IsMatch(request)) await hook.OnCallFailedStatus(request); }); } + else + { + _logger.LogError($"Unknown call status: {request.CallStatus}, {request.CallSid}"); + } return Ok(); } diff --git a/src/Plugins/BotSharp.Plugin.Twilio/Services/TwilioService.cs b/src/Plugins/BotSharp.Plugin.Twilio/Services/TwilioService.cs index c0254c1e..7bc95382 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/Services/TwilioService.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/Services/TwilioService.cs @@ -6,6 +6,8 @@ using BotSharp.Core.Infrastructures; using BotSharp.Plugin.Twilio.Interfaces; using BotSharp.Plugin.Twilio.Models; using Twilio.Jwt.AccessToken; +using Twilio.Rest.Api.V2010.Account.Call; +using Task = System.Threading.Tasks.Task; using Token = Twilio.Jwt.AccessToken.Token; namespace BotSharp.Plugin.Twilio.Services; @@ -122,6 +124,22 @@ public class TwilioService return response; } + public async Task StartRecording(string callSid, string agentId, string conversationId) + { + if (_settings.RecordingEnabled) + { + // https://help.twilio.com/articles/360010317333-Recording-Incoming-Twilio-Voice-Calls + var recordStatusUrl = $"{_settings.CallbackHost}/twilio/record/status?agent-id={agentId}&conversation-id={conversationId}"; + var recording = await RecordingResource.CreateAsync(pathCallSid: callSid, + recordingStatusCallback: new Uri(recordStatusUrl), + trim: "trim-silence", + recordingChannels: "dual", + recordingTrack: "both"); + + _logger.LogInformation($"Recording started: {recording.CallSid} {recording.Sid}"); + } + } + public VoiceResponse HangUp(string speechPath) { var response = new VoiceResponse(); From a2cae379631fcc069d5d8363958b54d568407dc4 Mon Sep 17 00:00:00 2001 From: Chen Gong Date: Tue, 29 Apr 2025 16:52:43 -0500 Subject: [PATCH 08/14] add function util-crontab-task_wait --- .../Crontab/Models/TaskWaitArgs.cs | 14 +++++++ .../BotSharp.Core.Crontab.csproj | 3 ++ .../Functions/TaskWaitFn.cs | 38 +++++++++++++++++++ .../Hooks/CrontabUtilityHook.cs | 5 ++- .../functions/util-crontab-task_wait.json | 16 ++++++++ 5 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 src/Infrastructure/BotSharp.Abstraction/Crontab/Models/TaskWaitArgs.cs create mode 100644 src/Infrastructure/BotSharp.Core.Crontab/Functions/TaskWaitFn.cs create mode 100644 src/Infrastructure/BotSharp.Core.Crontab/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/util-crontab-task_wait.json diff --git a/src/Infrastructure/BotSharp.Abstraction/Crontab/Models/TaskWaitArgs.cs b/src/Infrastructure/BotSharp.Abstraction/Crontab/Models/TaskWaitArgs.cs new file mode 100644 index 00000000..9eb72854 --- /dev/null +++ b/src/Infrastructure/BotSharp.Abstraction/Crontab/Models/TaskWaitArgs.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BotSharp.Abstraction.Crontab.Models; + +public class TaskWaitArgs +{ + + [JsonPropertyName("delay_time")] + public int DelayTime { get; set; } +} diff --git a/src/Infrastructure/BotSharp.Core.Crontab/BotSharp.Core.Crontab.csproj b/src/Infrastructure/BotSharp.Core.Crontab/BotSharp.Core.Crontab.csproj index ff6c2368..f406ac97 100644 --- a/src/Infrastructure/BotSharp.Core.Crontab/BotSharp.Core.Crontab.csproj +++ b/src/Infrastructure/BotSharp.Core.Crontab/BotSharp.Core.Crontab.csproj @@ -16,6 +16,9 @@ + + PreserveNewest + PreserveNewest diff --git a/src/Infrastructure/BotSharp.Core.Crontab/Functions/TaskWaitFn.cs b/src/Infrastructure/BotSharp.Core.Crontab/Functions/TaskWaitFn.cs new file mode 100644 index 00000000..b4e63a76 --- /dev/null +++ b/src/Infrastructure/BotSharp.Core.Crontab/Functions/TaskWaitFn.cs @@ -0,0 +1,38 @@ +using BotSharp.Core.Crontab.Hooks; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BotSharp.Core.Crontab.Functions; + +public class TaskWaitFn : IFunctionCallback +{ + public string Name => $"{CrontabUtilityHook.PREFIX}task_wait"; + + private readonly ILogger _logger; + public TaskWaitFn(ILogger logger) + { + _logger = logger; + } + public async Task Execute(RoleDialogModel message) + { + try + { + var args = JsonSerializer.Deserialize(message.FunctionArgs); + if (args != null || args.DelayTime > 0) + { + await Task.Delay(args.DelayTime * 1000); + } + message.Content = "wait task completed"; + } + catch (Exception ex) + { + message.Content = "Unable to perform delay task"; + _logger.LogError(ex, "crontab wait task failed."); + } + return true; + } +} diff --git a/src/Infrastructure/BotSharp.Core.Crontab/Hooks/CrontabUtilityHook.cs b/src/Infrastructure/BotSharp.Core.Crontab/Hooks/CrontabUtilityHook.cs index ed150861..7fed754a 100644 --- a/src/Infrastructure/BotSharp.Core.Crontab/Hooks/CrontabUtilityHook.cs +++ b/src/Infrastructure/BotSharp.Core.Crontab/Hooks/CrontabUtilityHook.cs @@ -7,7 +7,8 @@ public class CrontabUtilityHook : IAgentUtilityHook { public const string PREFIX = "util-crontab-"; private const string SCHEDULE_TASK_FN = $"{PREFIX}schedule_task"; - + private const string TASK_WAIT_FN = $"{PREFIX}task_wait"; + public void AddUtilities(List utilities) { var items = new List @@ -15,7 +16,7 @@ public class CrontabUtilityHook : IAgentUtilityHook new AgentUtility { Name = UtilityName.ScheduleTask, - Functions = [new(SCHEDULE_TASK_FN)], + Functions = [new(SCHEDULE_TASK_FN), new(TASK_WAIT_FN)], Templates = [new($"{SCHEDULE_TASK_FN}.fn")] } }; diff --git a/src/Infrastructure/BotSharp.Core.Crontab/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/util-crontab-task_wait.json b/src/Infrastructure/BotSharp.Core.Crontab/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/util-crontab-task_wait.json new file mode 100644 index 00000000..b3ddd167 --- /dev/null +++ b/src/Infrastructure/BotSharp.Core.Crontab/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/util-crontab-task_wait.json @@ -0,0 +1,16 @@ +{ + "name": "util-crontab-task_wait", + "description": "wait for a peroid of time then process", + "parameters": { + "type": "object", + "properties": { + "delay_time": { + "type": "number", + "description": "delay time in seconds" + } + }, + "required": [ + "delay_time" + ] + } +} \ No newline at end of file From ba827378f025c85fef081617ccecdf413e41c06c Mon Sep 17 00:00:00 2001 From: Jack Date: Wed, 30 Apr 2025 15:51:09 +0800 Subject: [PATCH 09/14] Update AgentService.GetAgents.cs can't not find agent throw exception --- .../BotSharp.Core/Agents/Services/AgentService.GetAgents.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs index 6db0819a..9fe90e8c 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs @@ -48,8 +48,8 @@ public partial class AgentService if (profile == null) { - _logger.LogError($"Can't find agent {id}"); - return null; + //_logger.LogError($"Can't find agent {id}"); + throw new ArgumentException($"Can't find agent {id}"); } // Load llm config From 72752061edd6b363a188d5542ba103bed13f0bba Mon Sep 17 00:00:00 2001 From: "aden.chen" Date: Wed, 30 Apr 2025 15:57:53 +0800 Subject: [PATCH 10/14] Track phone call success state in application --- .../BotSharp.Abstraction/Infrastructures/Enums/StateConst.cs | 1 + .../OutboundPhoneCallHandler/Functions/OutboundPhoneCallFn.cs | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/Infrastructure/BotSharp.Abstraction/Infrastructures/Enums/StateConst.cs b/src/Infrastructure/BotSharp.Abstraction/Infrastructures/Enums/StateConst.cs index 038699ac..4b1af0e2 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Infrastructures/Enums/StateConst.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Infrastructures/Enums/StateConst.cs @@ -17,4 +17,5 @@ public class StateConst public const string SUB_CONVERSATION_ID = "sub_conversation_id"; public const string ORIGIN_CONVERSATION_ID = "origin_conversation_id"; public const string WEB_DRIVER_TASK_ID = "web_driver_task_id"; + public const string PHONE_CALL_SUCCESSED = "phone_call_successed"; } diff --git a/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/OutboundPhoneCallFn.cs b/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/OutboundPhoneCallFn.cs index b5ecf101..a8b786fe 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/OutboundPhoneCallFn.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/OutboundPhoneCallFn.cs @@ -7,6 +7,7 @@ using BotSharp.Core.Infrastructures; using BotSharp.Plugin.Twilio.Interfaces; using BotSharp.Plugin.Twilio.Models; using BotSharp.Plugin.Twilio.OutboundPhoneCallHandler.LlmContexts; +using Microsoft.AspNetCore.Cors.Infrastructure; using Twilio.Rest.Api.V2010.Account; using Twilio.Types; using Conversation = BotSharp.Abstraction.Conversations.Models.Conversation; @@ -123,6 +124,7 @@ public class OutboundPhoneCallFn : IFunctionCallback var originConversationId = convService.ConversationId; var entryAgentId = routing.EntryAgentId; + states.SetState(StateConst.PHONE_CALL_SUCCESSED, true); await ForkConversation(args, entryAgentId, originConversationId, newConversationId, call); message.Content = $"The call has been successfully queued. The initial information is as follows: {args.InitialMessage}."; @@ -130,6 +132,7 @@ public class OutboundPhoneCallFn : IFunctionCallback } else { + states.SetState(StateConst.PHONE_CALL_SUCCESSED, false); message.Content = $"Failed to make a call, status is {call.Status}."; return false; } From aaa72a23db5b86bec533c8accff3b4bc0878e48e Mon Sep 17 00:00:00 2001 From: "aden.chen" Date: Wed, 30 Apr 2025 15:59:31 +0800 Subject: [PATCH 11/14] remove unused namepace --- .../OutboundPhoneCallHandler/Functions/OutboundPhoneCallFn.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/OutboundPhoneCallFn.cs b/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/OutboundPhoneCallFn.cs index a8b786fe..d0957d35 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/OutboundPhoneCallFn.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/OutboundPhoneCallFn.cs @@ -7,7 +7,6 @@ using BotSharp.Core.Infrastructures; using BotSharp.Plugin.Twilio.Interfaces; using BotSharp.Plugin.Twilio.Models; using BotSharp.Plugin.Twilio.OutboundPhoneCallHandler.LlmContexts; -using Microsoft.AspNetCore.Cors.Infrastructure; using Twilio.Rest.Api.V2010.Account; using Twilio.Types; using Conversation = BotSharp.Abstraction.Conversations.Models.Conversation; From 91dda91ee1f82ae933a48a9ed4de3088a35146d2 Mon Sep 17 00:00:00 2001 From: Jack Date: Wed, 30 Apr 2025 17:13:53 +0800 Subject: [PATCH 12/14] Update AgentService.GetAgents.cs fix can't find agent issue --- .../Agents/Services/AgentService.GetAgents.cs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs index 9fe90e8c..0860598a 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs @@ -44,13 +44,17 @@ public partial class AgentService [SharpCache(10)] public async Task GetAgent(string id) { - var profile = _db.GetAgent(id); + if (string.IsNullOrWhiteSpace(id)) + { + return null; + } - if (profile == null) - { - //_logger.LogError($"Can't find agent {id}"); - throw new ArgumentException($"Can't find agent {id}"); - } + var profile = _db.GetAgent(id); + if (profile == null) + { + _logger.LogError($"Can't find agent {id}"); + return null; + } // Load llm config var agentSetting = _services.GetRequiredService(); From 221d175e1a101d3515339020174a247c6581835d Mon Sep 17 00:00:00 2001 From: "aden.chen" Date: Wed, 30 Apr 2025 20:36:58 +0800 Subject: [PATCH 13/14] Revert "Track phone call success state in application" This reverts commit 72752061edd6b363a188d5542ba103bed13f0bba. --- .../BotSharp.Abstraction/Infrastructures/Enums/StateConst.cs | 1 - .../OutboundPhoneCallHandler/Functions/OutboundPhoneCallFn.cs | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Infrastructures/Enums/StateConst.cs b/src/Infrastructure/BotSharp.Abstraction/Infrastructures/Enums/StateConst.cs index 4b1af0e2..038699ac 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Infrastructures/Enums/StateConst.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Infrastructures/Enums/StateConst.cs @@ -17,5 +17,4 @@ public class StateConst public const string SUB_CONVERSATION_ID = "sub_conversation_id"; public const string ORIGIN_CONVERSATION_ID = "origin_conversation_id"; public const string WEB_DRIVER_TASK_ID = "web_driver_task_id"; - public const string PHONE_CALL_SUCCESSED = "phone_call_successed"; } diff --git a/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/OutboundPhoneCallFn.cs b/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/OutboundPhoneCallFn.cs index d0957d35..b5ecf101 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/OutboundPhoneCallFn.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/OutboundPhoneCallHandler/Functions/OutboundPhoneCallFn.cs @@ -123,7 +123,6 @@ public class OutboundPhoneCallFn : IFunctionCallback var originConversationId = convService.ConversationId; var entryAgentId = routing.EntryAgentId; - states.SetState(StateConst.PHONE_CALL_SUCCESSED, true); await ForkConversation(args, entryAgentId, originConversationId, newConversationId, call); message.Content = $"The call has been successfully queued. The initial information is as follows: {args.InitialMessage}."; @@ -131,7 +130,6 @@ public class OutboundPhoneCallFn : IFunctionCallback } else { - states.SetState(StateConst.PHONE_CALL_SUCCESSED, false); message.Content = $"Failed to make a call, status is {call.Status}."; return false; } From 4a220ab2cdc304f19f76006c0a1b46c87e2f17c2 Mon Sep 17 00:00:00 2001 From: Chen Gong Date: Wed, 30 Apr 2025 09:11:22 -0500 Subject: [PATCH 14/14] fix comments --- .../BotSharp.Core.Crontab/Functions/TaskWaitFn.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Infrastructure/BotSharp.Core.Crontab/Functions/TaskWaitFn.cs b/src/Infrastructure/BotSharp.Core.Crontab/Functions/TaskWaitFn.cs index b4e63a76..0fb68dc9 100644 --- a/src/Infrastructure/BotSharp.Core.Crontab/Functions/TaskWaitFn.cs +++ b/src/Infrastructure/BotSharp.Core.Crontab/Functions/TaskWaitFn.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; +using System.Text.Json.Serialization; using System.Threading.Tasks; namespace BotSharp.Core.Crontab.Functions; @@ -22,12 +23,17 @@ public class TaskWaitFn : IFunctionCallback try { var args = JsonSerializer.Deserialize(message.FunctionArgs); - if (args != null || args.DelayTime > 0) + if (args != null && args.DelayTime > 0) { await Task.Delay(args.DelayTime * 1000); } message.Content = "wait task completed"; } + catch (JsonException jsonEx) + { + message.Content = "Invalid function arguments format."; + _logger.LogError(jsonEx, "Json deserialization failed."); + } catch (Exception ex) { message.Content = "Unable to perform delay task";