using BotSharp.Abstraction.Conversations.Enums;
using BotSharp.Abstraction.Routing.Models;
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}]" + "}";
}
}