using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Functions.Models; using BotSharp.Abstraction.Planning; using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing.Models; using BotSharp.Abstraction.Routing.Settings; using System.Drawing; namespace BotSharp.Core.Routing; public partial class RoutingService : IRoutingService { private readonly IServiceProvider _services; private readonly RoutingSettings _settings; private readonly IRouterInstance _routerInstance; private readonly ILogger _logger; private List _dialogs; public List Dialogs { get { if (_dialogs == null) { var conv = _services.GetRequiredService(); _dialogs = conv.GetDialogHistory(); } return _dialogs; } } public void ResetRecursiveCounter() { _currentRecursionDepth = 0; } public void RefreshDialogs() { _dialogs = null; } public RoutingService(IServiceProvider services, RoutingSettings settings, ILogger logger, IRouterInstance routerInstance) { _services = services; _settings = settings; _logger = logger; _routerInstance = routerInstance; } public async Task ExecuteOnce(Agent agent, RoleDialogModel message) { var handlers = _services.GetServices(); var handler = handlers.FirstOrDefault(x => x.Name == "route_to_agent"); handler.SetDialogs(Dialogs); var result = await handler.Handle(this, new FunctionCallFromLlm { Function = "route_to_agent", Question = message.Content, Reason = message.Content, AgentName = agent.Name }, message); return result; } public async Task InstructLoop(RoleDialogModel message) { _routerInstance.Load(); var router = _routerInstance.Router; var context = _services.GetRequiredService(); var planner = _services.GetRequiredService(); var executor = _services.GetRequiredService(); int loopCount = 0; var stop = false; while (!stop && loopCount < 5) { loopCount++; var conversation = await GetConversationContent(Dialogs); router.TemplateDict["conversation"] = conversation; // Get instruction from Planner var inst = await planner.GetNextInstruction(router); // Save states SaveStateByArgs(inst.Arguments); #if DEBUG Console.WriteLine($"*** Next Instruction *** {inst}", Color.GreenYellow); #else _logger.LogInformation($"*** Next Instruction *** {inst}"); #endif await planner.AgentExecuting(inst, message); // Handle instruction by Executor var executed = await executor.Execute(this, router, inst, Dialogs, message); await planner.AgentExecuted(inst, message); // There is no need for the agent to continue processing, indicating that the task has been completed. if (context.IsEmpty || context.GetCurrentAgentId() == router.Id) { break; } } return true; } protected void SaveStateByArgs(JsonDocument args) { if (args == null) { return; } var stateService = _services.GetRequiredService(); if (args.RootElement is JsonElement root) { foreach (JsonProperty property in root.EnumerateObject()) { if (!string.IsNullOrEmpty(property.Value.ToString())) { stateService.SetState(property.Name, property.Value); } } } } }