using BotSharp.Abstraction.Conversations.Enums; using BotSharp.Abstraction.Routing.Models; using System.Drawing; namespace BotSharp.Core.Routing; public partial class RoutingService { /// /// If the target agent needs some required fields but the /// /// public (bool, string) HasMissingRequiredField(RoleDialogModel message, out string agentId) { var reason = string.Empty; var args = JsonSerializer.Deserialize(message.FunctionArgs); var routing = _services.GetRequiredService(); var routingRules = routing.GetRulesByAgentName(args.AgentName); if (routingRules == null || !routingRules.Any()) { agentId = message.CurrentAgentId; return (false, reason); } agentId = routingRules.First().AgentId; // Add routed agent message.FunctionArgs = AppendPropertyToArgs(message.FunctionArgs, "route_to", agentId); // Check required fields var root = JsonSerializer.Deserialize(message.FunctionArgs); var missingFields = new List(); foreach (var field in routingRules.Where(x => x.Required).Select(x => x.Field)) { if (!root.EnumerateObject().Any(x => x.Name == field)) { missingFields.Add(field); } else if (root.EnumerateObject().Any(x => x.Name == field) && string.IsNullOrEmpty(root.EnumerateObject().FirstOrDefault(x => x.Name == field).Value.ToString())) { missingFields.Add(field); } } // Check if states contains the field according conversation context. var states = _services.GetRequiredService(); foreach (var field in missingFields.ToList()) { if (!string.IsNullOrEmpty(states.GetState(field))) { var value = states.GetState(field); // Check if the value is correct data type var rule = routingRules.First(x => x.Field == field); if (rule.FieldType == "number") { if (!long.TryParse(value, out var longValue)) { states.SetState(field, "", isNeedVersion: true, source: StateSource.Application); continue; } } message.FunctionArgs = AppendPropertyToArgs(message.FunctionArgs, field, value); missingFields.Remove(field); } } if (missingFields.Any()) { var logger = _services.GetRequiredService>(); // Add field to args message.FunctionArgs = AppendPropertyToArgs(message.FunctionArgs, "missing_fields", missingFields); reason = $"missing some information: {string.Join(", ", missingFields)}"; // message.Content = reason; logger.LogWarning(reason); // Handle redirect var routingRule = routingRules.FirstOrDefault(x => missingFields.Contains(x.Field)); if (!string.IsNullOrEmpty(routingRule.RedirectTo)) { var db = _services.GetRequiredService(); var record = db.GetAgent(routingRule.RedirectTo); // Add redirected agent message.FunctionArgs = AppendPropertyToArgs(message.FunctionArgs, "redirect_to", record.Name); agentId = routingRule.RedirectTo; #if DEBUG Console.WriteLine($"*** Routing redirect to {record.Name.ToUpper()} ***"); #else logger.LogInformation($"*** Routing redirect to {record.Name.ToUpper()} ***"); #endif } else { // back to router agentId = message.CurrentAgentId; } } return (missingFields.Any(), reason); } private string AppendPropertyToArgs(string args, string key, string value) { return args.Substring(0, args.Length - 1) + $", \"{key}\": \"{value}\"" + "}"; } private string AppendPropertyToArgs(string args, string key, IEnumerable values) { string fields = string.Join(",", values.Select(x => $"\"{x}\"")); return args.Substring(0, args.Length - 1) + $", \"{key}\": [{fields}]" + "}"; } }