add utility visibility expression

This commit is contained in:
Jicheng Lu 2025-05-27 15:23:37 -05:00
parent 1672374e48
commit 28d4f4e9ba
7 changed files with 61 additions and 15 deletions

View file

@ -36,6 +36,8 @@ public interface IAgentService
FunctionParametersDef? RenderFunctionProperty(Agent agent, FunctionDef def);
bool RenderUtility(Agent agent, AgentUtility utility);
/// <summary>
/// Get agent detail without trigger any hook.
/// </summary>

View file

@ -4,6 +4,10 @@ public class AgentUtility
{
public string Name { get; set; }
public bool Disabled { get; set; }
[JsonPropertyName("visibility_expression")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? VisibilityExpression { get; set; }
public IEnumerable<UtilityFunction> Functions { get; set; } = [];
public IEnumerable<UtilityTemplate> Templates { get; set; } = [];

View file

@ -19,9 +19,9 @@ public class BasicAgentHook : AgentHookBase
var isConvMode = conv.IsConversationMode();
if (!isConvMode) return;
agent.Utilities ??= [];
agent.SecondaryFunctions ??= [];
agent.SecondaryInstructions ??= [];
agent.Utilities ??= [];
var (functions, templates) = GetUtilityContent(agent);
@ -34,7 +34,7 @@ public class BasicAgentHook : AgentHookBase
private (IEnumerable<FunctionDef>, IEnumerable<AgentTemplate>) GetUtilityContent(Agent agent)
{
var db = _services.GetRequiredService<IBotSharpRepository>();
var (functionNames, templateNames) = GetUniqueContent(agent.Utilities);
var (functionNames, templateNames) = FilterUtilityContent(agent.Utilities, agent);
if (agent.MergeUtility)
{
@ -43,7 +43,7 @@ public class BasicAgentHook : AgentHookBase
if (!string.IsNullOrEmpty(entryAgentId))
{
var entryAgent = db.GetAgent(entryAgentId, basicsOnly: true);
var (fns, tps) = GetUniqueContent(entryAgent?.Utilities);
var (fns, tps) = FilterUtilityContent(entryAgent?.Utilities, agent);
functionNames = functionNames.Concat(fns).Distinct().ToList();
templateNames = templateNames.Concat(tps).Distinct().ToList();
}
@ -55,22 +55,34 @@ public class BasicAgentHook : AgentHookBase
return (functions, templates);
}
private (IEnumerable<string>, IEnumerable<string>) GetUniqueContent(IEnumerable<AgentUtility>? utilities)
private (IEnumerable<string>, IEnumerable<string>) FilterUtilityContent(IEnumerable<AgentUtility>? utilities, Agent agent)
{
if (utilities.IsNullOrEmpty())
{
return ([], []);
}
utilities = utilities?.Where(x => !string.IsNullOrEmpty(x.Name) && !x.Disabled)?.ToList() ?? [];
var functionNames = utilities.SelectMany(x => x.Functions)
.Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX))
.Select(x => x.Name)
.Distinct().ToList();
var templateNames = utilities.SelectMany(x => x.Templates)
.Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX))
.Select(x => x.Name)
.Distinct().ToList();
var agentService = _services.GetRequiredService<IAgentService>();
var innerUtilities = utilities!.Where(x =>
{
var isVisible = !string.IsNullOrEmpty(x.Name) && !x.Disabled;
if (!isVisible)
{
return isVisible;
}
isVisible = agentService.RenderUtility(agent, x);
return isVisible;
}).ToList();
var functionNames = innerUtilities.SelectMany(x => x.Functions)
.Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX))
.Select(x => x.Name)
.Distinct().ToList();
var templateNames = innerUtilities.SelectMany(x => x.Templates)
.Where(x => !string.IsNullOrEmpty(x.Name) && x.Name.StartsWith(UTIL_PREFIX))
.Select(x => x.Name)
.Distinct().ToList();
return (functionNames, templateNames);
}

View file

@ -1,4 +1,3 @@
using BotSharp.Abstraction.Infrastructures;
using BotSharp.Abstraction.Routing.Models;
using System.Collections.Concurrent;
@ -18,12 +17,15 @@ public partial class AgentService
var agent = await GetAgent(id);
if (agent == null) return null;
agent.TemplateDict = [];
agent.SecondaryInstructions = [];
agent.SecondaryFunctions = [];
await InheritAgent(agent);
OverrideInstructionByChannel(agent);
AddOrUpdateParameters(agent);
// Populate state into dictionary
agent.TemplateDict = new Dictionary<string, object>();
PopulateState(agent.TemplateDict);
// After agent is loaded

View file

@ -1,5 +1,6 @@
using BotSharp.Abstraction.Loggers;
using BotSharp.Abstraction.Templating;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json.Linq;
namespace BotSharp.Core.Agents.Services;
@ -137,4 +138,20 @@ public partial class AgentService
return content;
}
public bool RenderUtility(Agent agent, AgentUtility utility)
{
if (string.IsNullOrWhiteSpace(utility?.VisibilityExpression))
{
return true;
}
var render = _services.GetRequiredService<ITemplateRender>();
var result = render.Render(utility.VisibilityExpression, new Dictionary<string, object>
{
{ "states", agent.TemplateDict }
});
return result == "visible";
}
}

View file

@ -7,6 +7,7 @@ public class AgentUtilityMongoElement
{
public string Name { get; set; } = default!;
public bool Disabled { get; set; }
public string? VisibilityExpression { get; set; }
public List<UtilityFunctionMongoElement> Functions { get; set; } = [];
public List<UtilityTemplateMongoElement> Templates { get; set; } = [];
@ -16,6 +17,7 @@ public class AgentUtilityMongoElement
{
Name = utility.Name,
Disabled = utility.Disabled,
VisibilityExpression = utility.VisibilityExpression,
Functions = utility.Functions?.Select(x => new UtilityFunctionMongoElement(x.Name))?.ToList() ?? [],
Templates = utility.Templates?.Select(x => new UtilityTemplateMongoElement(x.Name))?.ToList() ?? []
};
@ -27,6 +29,7 @@ public class AgentUtilityMongoElement
{
Name = utility.Name,
Disabled = utility.Disabled,
VisibilityExpression = utility.VisibilityExpression,
Functions = utility.Functions?.Select(x => new UtilityFunction(x.Name))?.ToList() ?? [],
Templates = utility.Templates?.Select(x => new UtilityTemplate(x.Name))?.ToList() ?? []
};

View file

@ -6,6 +6,7 @@ using BotSharp.Abstraction.Models;
using BotSharp.Abstraction.Plugins.Models;
using BotSharp.Abstraction.Repositories.Filters;
using BotSharp.Abstraction.Utilities;
using NetTopologySuite.Algorithm;
namespace BotSharp.Plugin.Google.Core
{
@ -61,6 +62,11 @@ namespace BotSharp.Plugin.Google.Core
return def.Parameters;
}
public bool RenderUtility(Agent agent, AgentUtility utility)
{
return true;
}
public Task<Agent> GetAgent(string id)
{
return Task.FromResult(new Agent());