using BotSharp.Abstraction.Loggers; using BotSharp.Abstraction.Templating; using Newtonsoft.Json.Linq; namespace BotSharp.Core.Agents.Services; public partial class AgentService { public string RenderedInstruction(Agent agent) { var render = _services.GetRequiredService(); var conv = _services.GetRequiredService(); // merge instructions var instructions = new List { agent.Instruction }; var secondaryInstructions = agent.SecondaryInstructions?.Where(x => !string.IsNullOrWhiteSpace(x)).ToList() ?? []; instructions.AddRange(secondaryInstructions); // update states foreach (var t in conv.States.GetStates()) { agent.TemplateDict[t.Key] = t.Value; } RenderAgentLinks(agent, agent.TemplateDict); var res = render.Render(string.Join("\r\n", instructions), agent.TemplateDict); return res; } public bool RenderFunction(Agent agent, FunctionDef def) { var isRender = true; var channels = def.Channels; if (channels != null) { var state = _services.GetRequiredService(); var channel = state.GetState("channel"); if (!string.IsNullOrWhiteSpace(channel)) { isRender = isRender && channels.Contains(channel); } } if (!isRender) return false; if (!string.IsNullOrWhiteSpace(def.VisibilityExpression)) { var render = _services.GetRequiredService(); var result = render.Render(def.VisibilityExpression, new Dictionary { { "states", agent.TemplateDict } }); isRender = isRender && result == "visible"; } return isRender; } public FunctionParametersDef? RenderFunctionProperty(Agent agent, FunctionDef def) { var parameterDef = def?.Parameters; var propertyDef = parameterDef?.Properties; if (propertyDef == null) return null; var visibleExpress = "visibility_expression"; var root = propertyDef.RootElement; var iterator = root.EnumerateObject(); var visibleProps = new List(); while (iterator.MoveNext()) { var prop = iterator.Current; var name = prop.Name; var node = prop.Value; var matched = true; if (node.TryGetProperty(visibleExpress, out var element)) { var expression = element.GetString(); var render = _services.GetRequiredService(); var result = render.Render(expression, new Dictionary { { "states", agent.TemplateDict } }); matched = result == "visible"; } if (matched) { visibleProps.Add(name); } } var rootObject = JObject.Parse(root.GetRawText()); var clonedRoot = rootObject.DeepClone() as JObject; var required = parameterDef?.Required ?? new List(); foreach (var property in rootObject.Properties()) { if (visibleProps.Contains(property.Name)) { var value = clonedRoot.GetValue(property.Name) as JObject; if (value != null && value.ContainsKey(visibleExpress)) { value.Remove(visibleExpress); } } else { clonedRoot.Remove(property.Name); required.Remove(property.Name); } } parameterDef.Properties = JsonSerializer.Deserialize(clonedRoot.ToString()); parameterDef.Required = required; return parameterDef; } public string RenderedTemplate(Agent agent, string templateName) { var conv = _services.GetRequiredService(); var render = _services.GetRequiredService(); var template = agent.Templates.FirstOrDefault(x => x.Name == templateName)?.Content ?? string.Empty; // update states foreach (var t in conv.States.GetStates()) { agent.TemplateDict[t.Key] = t.Value; } // render liquid template var content = render.Render(template, agent.TemplateDict); HookEmitter.Emit(_services, async hook => await hook.OnRenderingTemplate(agent, templateName, content) ).Wait(); return content; } private void RenderAgentLinks(Agent agent, Dictionary dict) { var render = _services.GetRequiredService(); var links = new Dictionary(); agent.Links ??= []; foreach (var link in agent.Links) { if (string.IsNullOrWhiteSpace(link.Name) || string.IsNullOrWhiteSpace(link.Content)) { continue; } links[link.Name] = link.Content; } render.RegisterTag("link", links, dict); return; } }