diff --git a/src/Infrastructure/BotSharp.Core.Realtime/Services/RealtimeHub.cs b/src/Infrastructure/BotSharp.Core.Realtime/Services/RealtimeHub.cs index 0e6027da..7dc34f27 100644 --- a/src/Infrastructure/BotSharp.Core.Realtime/Services/RealtimeHub.cs +++ b/src/Infrastructure/BotSharp.Core.Realtime/Services/RealtimeHub.cs @@ -98,24 +98,33 @@ public class RealtimeHub : IRealtimeHub routing.Context.SetDialogs(dialogs); + var states = _services.GetRequiredService(); + await _completer.Connect(_conn, onModelReady: async () => { - // Control initial session, prevent initial response interruption - await _completer.UpdateSession(_conn, turnDetection: false); - - if (dialogs.LastOrDefault()?.Role == AgentRole.Assistant) + if (states.ContainsState("init_audio_file")) { - await _completer.TriggerModelInference($"Rephase your last response:\r\n{dialogs.LastOrDefault()?.Content}"); + await _completer.UpdateSession(_conn, turnDetection: true); } else { - await _completer.TriggerModelInference("Reply based on the conversation context."); - } + // Control initial session, prevent initial response interruption + await _completer.UpdateSession(_conn, turnDetection: false); - // Start turn detection - await Task.Delay(1000 * 8); - await _completer.UpdateSession(_conn, turnDetection: true); + if (dialogs.LastOrDefault()?.Role == AgentRole.Assistant) + { + await _completer.TriggerModelInference($"Rephase your last response:\r\n{dialogs.LastOrDefault()?.Content}"); + } + else + { + await _completer.TriggerModelInference("Reply based on the conversation context."); + } + + // Start turn detection + await Task.Delay(1000 * 8); + await _completer.UpdateSession(_conn, turnDetection: true); + } }, onModelAudioDeltaReceived: async (audioDeltaData, itemId) => { diff --git a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioStreamController.cs b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioStreamController.cs index dcb33959..7fb7e0e0 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioStreamController.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioStreamController.cs @@ -44,7 +44,8 @@ public class TwilioStreamController : TwilioController if (_context.HttpContext.Request.Query.ContainsKey("init_audio_file")) { - instruction.SpeechPaths.Add(_context.HttpContext.Request.Query["init_audio_file"]); + request.InitAudioFile = _context.HttpContext.Request.Query["init_audio_file"]; + instruction.SpeechPaths.Add(request.InitAudioFile); } if (_context.HttpContext.Request.Query.ContainsKey("conversation_id")) @@ -104,6 +105,11 @@ public class TwilioStreamController : TwilioController new(StateConst.ROUTING_MODE, "lazy"), }; + if (request.InitAudioFile != null) + { + states.Add(new("init_audio_file", request.InitAudioFile)); + } + convService.SetConversationId(conversation.Id, states); convService.SaveStates(); diff --git a/src/Plugins/BotSharp.Plugin.Twilio/Models/ConversationalVoiceRequest.cs b/src/Plugins/BotSharp.Plugin.Twilio/Models/ConversationalVoiceRequest.cs index 33ee7633..a17b344f 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/Models/ConversationalVoiceRequest.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/Models/ConversationalVoiceRequest.cs @@ -18,6 +18,7 @@ public class ConversationalVoiceRequest : VoiceRequest public string? AIResponseErrorMessage { get; set; } = string.Empty; public string Intent { get; set; } = string.Empty; + public string? InitAudioFile { get; set; } public List States { get; set; } = []; }