Merge pull request #1106 from iceljc/features/refine-agent-template-link

Features/refine agent template link
This commit is contained in:
iceljc 2025-07-23 09:57:52 -05:00 committed by GitHub
commit 7bec0fa720
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 50 additions and 10 deletions

View file

@ -475,7 +475,7 @@ namespace BotSharp.Core.Repository
if (!filter.AgentNames.IsNullOrEmpty()) if (!filter.AgentNames.IsNullOrEmpty())
{ {
query = query.Where(x => filter.AgentNames.Contains(x.Name)); query = query.Where(x => filter.AgentNames.Contains(x.Name, StringComparer.OrdinalIgnoreCase));
} }
if (!string.IsNullOrEmpty(filter.SimilarName)) if (!string.IsNullOrEmpty(filter.SimilarName))

View file

@ -4,10 +4,12 @@ using BotSharp.Abstraction.Templating;
using BotSharp.Abstraction.Translation.Models; using BotSharp.Abstraction.Translation.Models;
using Fluid; using Fluid;
using Fluid.Ast; using Fluid.Ast;
using Fluid.Values;
using System.Collections; using System.Collections;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using System.Text.RegularExpressions;
namespace BotSharp.Core.Templating; namespace BotSharp.Core.Templating;
@ -36,9 +38,11 @@ public class TemplateRender : ITemplateRender
_options.MemberAccessStrategy.Register<UserIdentity>(); _options.MemberAccessStrategy.Register<UserIdentity>();
_options.MemberAccessStrategy.Register<TranslationInput>(); _options.MemberAccessStrategy.Register<TranslationInput>();
_parser.RegisterIdentifierTag("link", (string identifier, TextWriter writer, TextEncoder encoder, TemplateContext context) => _options.Filters.AddFilter("from_agent", FromAgentFilter);
_parser.RegisterExpressionTag("link", (Expression expression, TextWriter writer, TextEncoder encoder, TemplateContext context) =>
{ {
return RenderIdentifierTag("link", identifier, writer, encoder, context); return RenderTag("link", expression, writer, encoder, context, services);
}); });
} }
@ -82,20 +86,46 @@ public class TemplateRender : ITemplateRender
#region Private methods #region Private methods
private static async ValueTask<Completion> RenderIdentifierTag(string tag, string identifier, TextWriter writer, TextEncoder encoder, TemplateContext context) private static async ValueTask<Completion> RenderTag(
string tag,
Expression expression,
TextWriter writer,
TextEncoder encoder,
TemplateContext context,
IServiceProvider services)
{ {
try try
{ {
var value = await context.Model.GetValueAsync(TemplateRenderConstant.RENDER_AGENT, context); var value = await expression.EvaluateAsync(context);
var agent = value?.ToObjectValue() as Agent; var expStr = value?.ToStringValue() ?? string.Empty;
var found = agent?.Templates?.FirstOrDefault(x => x.Name.IsEqualTo(identifier));
var key = $"{agent?.Id} | {tag} | {identifier}";
if (found == null || (context.AmbientValues.TryGetValue(key, out var visited) && (bool)visited)) value = await context.Model.GetValueAsync(TemplateRenderConstant.RENDER_AGENT, context);
var agent = value?.ToObjectValue() as Agent;
var splited = Regex.Split(expStr, @"\s*from_agent\s*", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)
.Where(x => !string.IsNullOrWhiteSpace(x))
.Select(x => x.Trim())
.ToArray();
var templateName = splited.ElementAtOrDefault(0);
var agentName = splited.ElementAtOrDefault(1);
if (splited.Length > 1 && !agentName.IsEqualTo(agent?.Name))
{
using var scope = services.CreateScope();
var agentService = scope.ServiceProvider.GetRequiredService<IAgentService>();
var result = await agentService.GetAgents(new() { SimilarName = agentName });
agent = result?.Items?.FirstOrDefault();
}
var template = agent?.Templates?.FirstOrDefault(x => x.Name.IsEqualTo(templateName));
var key = $"{tag} | {agent?.Id} | {templateName}";
if (template == null || (context.AmbientValues.TryGetValue(key, out var visited) && (bool)visited))
{ {
writer.Write(string.Empty); writer.Write(string.Empty);
} }
else if (_parser.TryParse(found.Content, out var t, out _)) else if (_parser.TryParse(template.Content, out var t, out _))
{ {
context.AmbientValues[key] = true; context.AmbientValues[key] = true;
var rendered = t.Render(context); var rendered = t.Render(context);
@ -115,6 +145,16 @@ public class TemplateRender : ITemplateRender
return Completion.Normal; return Completion.Normal;
} }
private static ValueTask<FluidValue> FromAgentFilter(
FluidValue input,
FilterArguments arguments,
TemplateContext context)
{
var inputStr = input?.ToStringValue() ?? string.Empty;
var fromAgent = arguments.At(0).ToStringValue();
return new StringValue($"{inputStr} from_agent {fromAgent}");
}
private static bool IsStringType(Type type) private static bool IsStringType(Type type)
{ {
return type == typeof(string); return type == typeof(string);