diff --git a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs index 7c2466d9..45fd3251 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Agents/IAgentService.cs @@ -12,7 +12,7 @@ public interface IAgentService Task CreateAgent(Agent agent); Task RefreshAgents(); Task> GetAgents(AgentFilter filter); - Task> GetAgentOptions(List? agentIds = null); + Task> GetAgentOptions(List? agentIds = null, bool byName = false); /// /// Load agent configurations and trigger hooks diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs index 6f96eec5..de269759 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs @@ -66,6 +66,12 @@ public class RoleDialogModel : ITrackableMessage [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? FunctionArgs { get; set; } + /// + /// Set this flag is in OnFunctionExecuting, if true, it won't be executed by InvokeFunction. + /// + [JsonIgnore(Condition = JsonIgnoreCondition.Always)] + public bool Handled { get; set; } = false; + /// /// Function execution structured data, this data won't pass to LLM. /// It's ideal to render in rich content in UI. diff --git a/src/Infrastructure/BotSharp.Core.Realtime/Hooks/RealtimeConversationHook.cs b/src/Infrastructure/BotSharp.Core.Realtime/Hooks/RealtimeConversationHook.cs index 85c7d24c..ed53be79 100644 --- a/src/Infrastructure/BotSharp.Core.Realtime/Hooks/RealtimeConversationHook.cs +++ b/src/Infrastructure/BotSharp.Core.Realtime/Hooks/RealtimeConversationHook.cs @@ -63,7 +63,7 @@ public class RealtimeConversationHook : ConversationHookBase, IConversationHook } else { - await hub.Completer.TriggerModelInference($"{instruction}\r\n\r\nResponse user based on function result"); + await hub.Completer.TriggerModelInference(instruction); } } } diff --git a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs index b07a64ff..6db0819a 100644 --- a/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs +++ b/src/Infrastructure/BotSharp.Core/Agents/Services/AgentService.GetAgents.cs @@ -26,12 +26,18 @@ public partial class AgentService } [SharpCache(10)] - public async Task> GetAgentOptions(List? agentIds) + public async Task> GetAgentOptions(List? agentIdsOrNames, bool byName = false) { - var agents = _db.GetAgents(new AgentFilter - { - AgentIds = !agentIds.IsNullOrEmpty() ? agentIds : null - }); + var agents = byName ? + _db.GetAgents(new AgentFilter + { + AgentNames = !agentIdsOrNames.IsNullOrEmpty() ? agentIdsOrNames : null + }) : + _db.GetAgents(new AgentFilter + { + AgentIds = !agentIdsOrNames.IsNullOrEmpty() ? agentIdsOrNames : null + }); + return agents?.Select(x => new IdName(x.Id, x.Name))?.OrderBy(x => x.Name)?.ToList() ?? []; } diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingContext.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingContext.cs index 63049738..4cba2e2d 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingContext.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingContext.cs @@ -86,10 +86,12 @@ public class RoutingContext : IRoutingContext if (!Guid.TryParse(agentId, out _)) { var agentService = _services.GetRequiredService(); - agentId = agentService.GetAgents(new AgentFilter + var agents = agentService.GetAgentOptions([agentId], byName: true).Result; + + if (agents.Count > 0) { - AgentNames = [agentId] - }).Result.Items.First().Id; + agentId = agents.First().Id; + } } if (_stack.Count == 0 || _stack.Peek() != agentId) diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeFunction.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeFunction.cs index ee403ff8..8c37536c 100644 --- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeFunction.cs +++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.InvokeFunction.cs @@ -49,8 +49,11 @@ public partial class RoutingService await progressService.OnFunctionExecuting(clonedMessage); } + var agentService = _services.GetRequiredService(); + var agent = await agentService.GetAgent(clonedMessage.CurrentAgentId); foreach (var hook in hooks) { + hook.SetAgent(agent); await hook.OnFunctionExecuting(clonedMessage); } @@ -58,7 +61,11 @@ public partial class RoutingService try { - if (!isFillDummyContent) + if (clonedMessage.Handled) + { + clonedMessage.Content = clonedMessage.Content; + } + else if (!isFillDummyContent) { result = await function.Execute(clonedMessage); } diff --git a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Realtime/RealTimeCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Realtime/RealTimeCompletionProvider.cs index e87f2226..924ac7f1 100644 --- a/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Realtime/RealTimeCompletionProvider.cs +++ b/src/Plugins/BotSharp.Plugin.OpenAI/Providers/Realtime/RealTimeCompletionProvider.cs @@ -162,7 +162,7 @@ public class RealTimeCompletionProvider : IRealTimeCompletion } else if (response.Type == "response.audio_transcript.delta") { - + _logger.LogDebug($"{response.Type}: {receivedText}"); } else if (response.Type == "response.audio_transcript.done") { @@ -211,9 +211,14 @@ public class RealTimeCompletionProvider : IRealTimeCompletion } else if (response.Type == "input_audio_buffer.speech_started") { + _logger.LogInformation($"{response.Type}: {receivedText}"); // Handle user interuption onInterruptionDetected(); } + else if (response.Type == "input_audio_buffer.speech_stopped") + { + _logger.LogInformation($"{response.Type}: {receivedText}"); + } } }